SQL Server 2005 Stored procedure problem contatenating string with wildcard - sql

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

Related

SQL Server: Dynamic SQL generated variable can print value but cannot store in new variable

DECLARE #listofelements NVARCHAR(4000)
SELECT #listofelements = COALESCE(#listofelements + ',', '') + '[' + OBJECT_SCHEMA_NAME(v.object_id) + '].[' + v.name +']' FROM sys.views as v
PRINT #listofelements
UPDATE [database].[dbo].[Table1] SET [Total_text] = #listofelements
The code above till the PRINT statement works fine. The print statement gives me a large text string which is what I want. This textstring looks to be generated on the fly. However, if I want to update a table in my database with this value #listofelements then it updates nothing. How come that #listofelements which is generated by the script is not able to update my Table1. It has nothing to do with the length of the string of type. It doesn't give an error, it just doesn't update. It looks like #listofelements is empty while on the other hand I can print it. Note: I ran all 5 lines at the same time.

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

A more elegant way of escaping dynamic 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)

SQL Query which returns records with data type date and value '01/01/2001'?

Hello I am currently converting data for a client. I am importing "|" delimited text files in to SQL Server 2008 R2. The customer has used '01/01/0001' as a blank date; however when i import this value SQL Server see's this date as "01/01/2001".
My original work around was importing as char(10) and then altering after the import. This worked for some but I have discovered that it doesn't always work!!!! Frustrating....
I need to do a search of all data types date with a value of '01/01/2001'
If you want to just update all instances to NULL (which is much better than some magic 01/01/0001 value) then you can say:
DECLARE #sql NVARCHAR(MAX) = N'';
SELECT #sql += N'
UPDATE '
+ QUOTENAME(OBJECT_SCHEMA_NAME([object_id]))
+ '.' + QUOTENAME(OBJECT_NAME([object_id]))
+ ' SET ' + QUOTENAME(name) + ' = NULL
WHERE ' + QUOTENAME(name) + ' = ''20010101'';'
FROM sys.columns
WHERE system_type_id = 40; -- date
PRINT #sql;
--EXEC sp_executesql #sql;
Now, I suspect the cases where this didn't work are cases where the data type is NOT in fact date but rather datetime / smalldatetime. So you may want this instead:
WHERE system_type_id IN (40,42,43,58,61);
If you still want to use this hocus pocus you can change this line:
+ ' SET ' + QUOTENAME(name) + ' = NULL
To this:
+ ' SET ' + QUOTENAME(name) + ' = ''00010101''
But this won't work if the column is datetime/smalldatetime!
Note that you should always use YYYYMMDD. This MM/DD/YYYY stuff is a bad habit and prone to misinterpretation up and down the stack.