A more elegant way of escaping dynamic SQL? - sql

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)

Related

how to concatenate Where clause with Like

I'm trying to concatenate SET #WhereClause= #WhereClause + 'con.BusinessName LIKE ' + '%'+CONVERT(VARCHAR,#BusinessName) + '%' + ' AND '; this line.
I want to result like this SET #WhereClause= con.BusinessName LIKE '%Hello%' AND ';
You should really be using parameters. But you need the single quotes:
'''%'+CONVERT(VARCHAR(255), #BusinessName) + '%'''
You should also specify the length for VARCHAR() in SQL Server. The default varies by context and debugging problems can be quite hard.
Note: This will fail if #BusinessName has a single quote. Think: parameters.
Also, you could use QUOTENAME function (SQL Server 2008 and above):
SET #WhereClause = #WhereClause + 'con.BusinessName LIKE ' + QUOTENAME('%' + CONVERT(varchar(126), #BusinessName) + '%', '''') + ' AND ';
With the QUOTENAME function you can avoid your code to break when #BusinessName contains single quote characters, and eliminate the possibility of SQL injection attacks as well (for example, if #BusinessName gets its value directly from an UI, via a query parametar or request body in a web application/APIs, etc.).
The QUOTENAME is intended for making valid delimited identifiers in dynamic SQL, but it could be used in your case.
The function accepts nvarchar(128) as an input string, and if the #BusinessName is longer than 126 characters (128 minus two % characters) it will return NULL. So, you should take care of that edge case.

Trying to use SQL Replace in a non-dynamic way

I have the following statement, where I'm passing in a parameter like this:
'0001,0003'
I was following the REPLACE answer from this question:
SQL IN Statement splitting parameter
But I'm trying to take it out of dynamic sql. My returned result is NULL. Is there anyway to get this to work?
DECLARE #partialLNum varchar(MAX)
DECLARE #lNumConCat varchar(500)
DECLARE #tTemp table(lNum varchar(15))
DECLARE #formatIN varchar(MAX)
set #partialLNum = '0001,0003'
set #formatIN = ''''+ REPLACE(#partialLNum,',',''',''')+''''
insert into #tTemp
select substring(lNum,1,2) + '-' + substring(lNum,3,3) + '-' + substring(lNum,6,2) + '-' + substring(lNum,8,3)
from [rpt].[myView]
where LNum IN (#formatIN)
select #lNumConCat = COALESCE(#lNumConCat +'' , '', '''') + LNum from #tTemp
select #lNumConCat
in takes a list of values. So:
where LNum IN ('0001,0003')
has a list with one element, that happens to have a comment in it.
One way to do what you want is using like:
where ',' + partialLNum + ',' like '%,' + LNum + ',%'
There should suffice, but there are other ways using a split() function as well.

Single quote in SQL WHERE IN statement

Okay so my T-SQL statement is the following
IF #dept <> '' BEGIN
SET #query = #query + ' AND T6.Region2 IN (' + REPLACE(#dept, '^', '''') + ') '
END
This is basically for a French site and the region names have ' in the names. What I'm trying to do is pass something like the following to SQL
#dept = 'Cote-d^Armor', 'Val-d^Oise'
and replace the ^ with a '. When I do a replace it's just causing an error as if the replaced ^ is a ' and escaping the rest of the code.
Hope that makes sense.
You need some extra quotes outside the replace. Try this:
IF #dept <> '' BEGIN
SET #query = #query + ' AND T6.Region2 IN (''' + REPLACE(#dept, '^', '''') + ''') '
END
I wouldn't swap "'" for "^" to store it and then try and convert it back. It would be much simpler to store "Cote-d'Armor", then in your stored procedure whenever there is a "'" in the search string, to double it.
SQL Server can happily cope with ' and " in the data, they just need to be escaped properly.

Spiliting values in query SQL

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

SQL Server 2005 Stored procedure problem contatenating string with wildcard

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