I am trying to perform the below query where some variables are being used. This below SQL code is a part of a stored procedure. Idea is to dynamically set the target columns and its values based on FileKey.
DECLARE #TargetColNames nvarchar(max) = '';
DECLARE #SourceColNames nvarchar(max) = '';
DECLARE #SourceColNamesInsert nvarchar(max) = '';
DECLARE #UpdateColumns nvarchar(max) = '';
SELECT
CASE
WHEN #FileKey IN ('s_1','s_2')
THEN #TargetColNames = #TargetColNames + ' [CreatedUser], [UpdatedUser], [CreatedDateTime],[UpdatedDateTime],[IsDeleted],[DeletedOn]'
ELSE #TargetColNames = #TargetColNames + ' [CreatedUser], [UpdatedUser], [CreatedDateTime], [UpdatedDateTime]'
END,
#SourceColNames = CONCAT('CreatedUser','UpdatedUser','CreatedDateTime', 'UpdatedDateTime'),
#SourceColNamesInsert = CONCAT(''',#User, ''',''',#User, ''', 'Getdate()', 'Getdate()' ),
CASE
WHEN #FileKey IN ('s_1','s_2')
THEN #UpdateColumns = CONCAT('Target.UpdatedUser= ''',#User,''', 'Target.[IsDeleted]=0','Target.[DeletedOn]=null')
ELSE #UpdateColumns = CONCAT('Target.UpdatedUser= ''',#User,''', 'Target.UpdatedDateTime=Getdate()')
END
The above SQL statement throws an error:
Msg 102, Level 15, State 1, Procedure uspDynamicStageToPropLayer1, Line 165 [Batch Start Line 5]
Incorrect syntax near '='.
What am I missing here? Maybe this is quite a silly mistake...
Also, by doing concat with your quoted parts, you might allow SQL injection into your query even building dynamically. What if a user's name (or forced parameter has a leading single quote, then garbage injection such as
#User = ';drop table X --
Having said that, some of the stuff could be more simplified, such as
SELECT
#TargetColNames = #TargetColNames
+ ' [CreatedUser], [UpdatedUser], [CreatedDateTime], [UpdatedDateTime]'
+ CASE WHEN #FileKey IN ('s_1','s_2')
THEN ', [IsDeleted], [DeletedOn]'
else ''
end
For the insert, you will probably get a failure. If you look at a possible result of the #User
#SourceColNamesInsert = concat(''',#User, ''',''',#User, ''',
'Getdate()', 'Getdate()' ),
will result with the value below which is not what I think is intended. Notice no comma's between values because the triple ' is creating start and end literals, and leaves no actual comma between column insert values.
',#User, '',#User, 'Getdate()Getdate()
But instead...
select concat('''#User'', ''#User''', ', Getdate(), Getdate()' );
which will result in...
'#User', '#User', Getdate(), Getdate()
The ''' actually creates an opening quoted string immediately with the value after it, then the '' (double) closes the quoted string, but it also adds the comma separator before the next '' (double) to start second user and ''' (triple) to close the second #User, then adding comma and both getdate() calls.
'#User', '#User', Getdate(), Getdate()
Now, if the value for #User was 'Bob', and your intent was to have the string output as
'Bob', 'Bob', Getdate(), Getdate()
change to
select concat('''', #User, ''', ','''', #User, '''', ', Getdate(), Getdate()' );
The '''' (quad) means I want to open a string, do a single quote (by the inner two ''), and close this as its own string. then get the value of the #User. Then follow by an open string ' with '' for closing the quote around the name, then open a single quote to start the next, the comma before starting the next quote for the second user and closing it as well via '''', then the value of the user again, and finally closing the second user with close quote ''''. Finally adding a comma and getdate() calls. Yes, stupid tricky in the quoting.
An easier implementation without CONCAT() is just using + between each explicit part such as
select '''' + #User + '''' + ', ' + '''' + #User + '''' + ', Getdate(), getdate()' ;
where each '''' is a single quote thus resulting in
' + Bob + ' + , + ' + Bob + ' + , Getdate(), getdate()
resulting in
'Bob', 'Bob', Getdate(), getdate()
I'll leave the final UpdateColumns to you to confirm your intended output.
But, as mentioned, beware of possible SQL injection when you are dynamically building SQL statements with embedded parameter values as this appears to be doing.
Here is another way to approach this:
Declare #FileKey varchar(10) = 's_3'
, #TargetColNames nvarchar(max) = ''
, #SourceColNames nvarchar(max) = ''
, #SourceColNamesInsert nvarchar(max) = ''
, #UpdateColumns nvarchar(max) = '';
Set #TargetColNames = concat_ws(', ', '[CreatedUser]', '[UpdatedUser]', '[CreatedDateTime]', '[UpdatedDateTime]');
If #FileKey In ('s_1', 's_2')
Set #TargetColNames = concat_ws(', ', #TargetColNames, '[UpdatedDateTime]', '[IsDeleted]', '[DeletedOn]');
Print #TargetColNames;
Set #SourceColNames = concat_ws(', ', '[CreatedUser]', '[UpdatedUser]', '[CreatedDateTime]', '[UpdatedDateTime]');
Set #SourceColNamesInsert = concat_ws(', ', quotename('#User', char(39)), quotename('Getdate()', char(39)), quotename('Getdate()', char(39)));
Print #SourceColNames;
Print #SourceColNamesInsert;
How to add space in this SQL text?
ISNULL('phone: ' + [phone],' ') + 'some space' + ISNULL('email: ' +[email],' ') +
What can be used in the place of 'some space ' so that space is put in between the texts ? any help , thank you.
EDITED
I want the phone and email displayed far apart eachother may be 100px in between them
SPACE function works in SQL but not in browser. what is wrong?
Instead of just writing some space, literally use spaces
('phone: ' + [phone],' ') + 'some space' + ('email: ' +[email],' ') +
to
('phone: ' + [phone],' ') + ' ' + ('email: ' +[email],' ') +
I'm unclear if this is what you're asking but, depending on your variant of SQL, you might not be able to concatenate text with "+".
Rather there is generally some flavor of the concat() or concatenate() function that serves this purpose.
eg. concat(isnull(concat('phone: ', [phone]),' '), 'some space')... etc
I think you want:
SELECT LTRIM(COALESCE(' phone: ' + [phone], '') + COALESCE(' email: ' + [email], ''))
This will return one or the other (or both) with no leading spaces.
If this is being displayed on a website, then one option is to make sure there is a clear 1-pixel gif on the website, and add the img tag for that gif and style it with the amount of horizontal space that you want.
But then I haven't done web dev in so long that 1-pixel gifs could be totally passe today for all I know.
Use ASCII code for horizontal tab which is CHAR(9) along with CONCAT function.
You can also do a function with a loop to set your spacing
DECLARE #tabSpacing varchar(50)='';
DECLARE #counter int = 50;
WHILE #counter>0
BEGIN
SET #tabSpacing+=CHAR(9);
SET #counter-=1;
END
SELECT CONCAT(ISNULL('phone: ' + [phone],' '),#tabSpacing,ISNULL('email: ' +[email],' ')) AS Info FROM Users
It may help someone when a need arises. My question was solved this way
DECLARE #wider_space NVARCHAR(50);
SET #wider_space = '& nbsp ; & nbsp ; & nbsp ; & nbsp;& nbsp ; & nbsp ;& nbsp ; & nbsp ;';
---avoid spaces when used
ISNULL('Phone: ' + [phone] + #wider_space,' ') + ISNULL('Email: ' +[email] + #wider_space,' ') + ...
and continues like this to concat 6 columns together.
I'm facing a problem right now.. what if the query itself contains code between bracket like foo and this foo is replaced with a declare-result value like #foo
when O want to print what's the container in #foo instead of 'foo' i should use '#foo' but sql reads it as '#foo' and ignores the # because it's between ' and '
In c# as usual, I do use "'"+#foo+"'" now in sql there's no ID for " so we use '
when i use '''+#foo+''' it does not read. although in c# we use something like \ between the brackets to get it done, sql does not read
What should I do in this case?
Image for the problem and query itself:
Sounds like you're wanting to escape single quotes.
To do this you need to double them up!
DECLARE #foo char(1);
SET #foo = 'A';
SELECT '''' As a_single_quote
, '''''' As a_pair_of_single_quotes
, '''' + 'TEST' + '''' As escaped_string
, '''' + #foo + '''' As with_a_variable
OK, so I've got this line of code in a search stored procedure:
SET #where = 'job_code = ''' + REPLACE(#job_code, '''', '''''') + ''''
and there are basically two operations I'd like to streamline -the first being surrounding the concatenated value in single quotes. Obviously, in the above statement, I'm escaping a ' by using two '' and then ending the string with a ' so I can concatenate the actual value. There's got to be a better way!
The second of the operations would be the REPLACE(#job_code, '''', '''''') where I'm escaping any single quotes that might exist in the field.
Isn't there a much more elegant way of writing this line of code as a whole?
I thought it was the ESCAPE keyword but that's tied tightly to the LIKE statement, so no go there.
Not sure how you execute your sql query, if you use sp_executesql, could be something like this
EXECUTE sp_executesql
N'SELECT * FROM YouTable WHERE job_code = #job_code',
N'#job_code varchar(100)',
#job_code = #job_code;
The parameterized query answer is probably the real "right answer", but to answer your original question, what you want is QUOTENAME(). More specifically, the single-quote version:
SET #where = 'job_code = ' + QUOTENAME(#job_code, '''')
Do note the length limit on this (input is a sysname, meaning 128 characters), though, as it is intended to quote the names of database objects and not as a general-purpose mechanism.
You could declare constants:
declare #SQ as char(1) = ''''
SET #where = 'job_code = ' + #SQ + REPLACE(#job_code, #SQ, #SQ + #SQ) + #SQ
You could define a function that handles your typical scenarios, something like:
create function WrapAndReplaceQuotes (#input as varchar(max))
returns varchar(max)
as
begin
return '''' + replace(#input, '''', '''''') + ''''
end
SET #where = 'job_code = ' + WrapAndReplaceQuotes(#job_code)
I have a lengthy stored procedure that builds a query string. It works fine until I add in a 'LIKE' description field (text) which has a wildcard in it, see below:
IF #AdDescription IS NOT NULL
IF #AdSection IS NOT NULL
BEGIN
SET #SQL = #SQL + #Wand + 'na.Section = '' + #AdDescription + '''
SET #Wand = ' AND '
END
ELSE
BEGIN
SET #SQL = #SQL + #Wand + '(na.AdDesc LIKE ''' + #AdDescription + '%'')'
SET #Wand = ' AND '
END
I've tried a few variations but as soon as #AdDescription has anything in it it fails. Is there something obvious that I am missing?
You are missing an apostrophe in your first "SET #SQL" line. There should be 3 apostrophes before you add the #AdDescription. The color coding in your code above shows this problem. The plus signs are red instead of black.
Try using print to see the SQl you have created, then you will likely see the error. And try really hard to avoid dynamic sql, it's hard to maintain, test, and debug properly.
Instead of exec the SQl just have it do:
Print #SQL
This will print the SQL Statement.
We usually havea debug parameter on any stored proc that uses dynamic SQl abd if it is set to 1, it prints the SQL and if it is set to 0 (the default), it executes the SQL. This makes it easier to see what is being created for a set of values later when the proc fails in production becasue of some obscure condition you didn't consider.
YOu can also get the SQl executed by running profiler, but usually it's simpler to just run with the same values in debug mode.
Edit Maybe it's just the quotes? I've added some spaces so the escaping is clearer.
IF #AdDescription IS NOT NULL
IF #AdSection IS NOT NULL
BEGIN
SET #SQL = #SQL + #Wand
+ 'na.Section = ' ''' + #AdDescription + ''' '
SET #Wand = ' AND '
END
ELSE
BEGIN
SET #SQL = #SQL + #Wand
+ '(na.AdDesc LIKE ' ''' + #AdDescription + '%'' )'
END