how to concatenate Where clause with Like - sql

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.

Related

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)

Why variable with nvarchar(max) work incorrect

Currently, I have a function to get list of columns of 1 table with detail attribute. And off course, there are some tables with a lot of columns. So, the output will be over 10.000 characters.
Here I test like this:
declare #aa nvarchar(max)
set #aa = dbo.fnGetColumnList('Table_Name')
print #aa
The result always has around 4000 characters. It looks like the SQL has truncated it.
What I know that when we declare nvarchar(max), SQL will supports up to 2^32-1 (2GB) for this string. But why it just has around 4000 characters?
When I execute like this:
select dbo.fnGetColumnList('Table_Name')
the result is correct.
And here is the code for the function:
-- get column list from table Mapping
ALTER FUNCTION [dbo].[fnGetColumnList] ( #tblName varchar (30))
RETURNS nvarchar(max)
AS
BEGIN
Declare #sql nvarchar(max)
set #sql = ''
SELECT #sql = #sql + case
when CHARINDEX('char', LOWER([DBType])) > 0 then ', ['+[DBColumn]+']' + ' ['+[DBType]+']' + ' ('+convert(varchar(10),[Length])+') NULL' + CHAR(13)
when CHARINDEX('char', LOWER([DBType])) > 0 then ', ['+[DBColumn]+']' + ' ['+[DBType]+']' + ' NULL' + CHAR(13)
ELSE ', ['+[DBColumn]+']' + ' ['+[DBType]+']' + ' NULL' + CHAR(13)
end FROM dbo.Mapping WHERE [DBTable] = #tblName
return #sql
END
Please advance.
This is almost always a variable assignment type problem, as explained in:
For Nvarchar(Max) I am only getting 4000 characters in TSQL?
If it's not that, then it's probably just the settings of Print to display too few characters:
nvarchar(max) still being truncated
Having looked at the updated code, it seems like it's the second issue, your print is truncating as it's not set to show enough characters.
You should see this by running
SELECT LEN(#aa)
You'll get a number larger than 4000, showing the value is held correctly in the variable.
As explained in Microsoft's nvar and nvarchar docs:
A common misconception is to think that with nchar(n) and nvarchar(n), the n defines the number of characters. However, in nchar(n) and nvarchar(n), the n defines the string length in byte-pairs (0-4,000). n never defines numbers of characters that can be stored. This is similar to the definition of char(n) and varchar(n).
There is an option in SQL Management Studio:
Tools > Options... > Query Results > SQL Server > Results to Text > Maximum number of characters displayed in each column

Issue With Apostrophe

I have a Proc that was coded in Dynamic SQl for one of my Application. It is using to search the Applicants with their last name. Right now it is searching applicants with either their first 2 digits of their last name or full last name. But i have a problem searching Applicants that have Apostrophe in their last name(Example O'Connor). If the client try to search applicant with O' or O'Connor it is throwing an error. They want to search every Applicant with or without Apostrophe in their last name. Please Help I tried everything, but its not working. Below is my search code that using in the Proc to pull applicants:
Add wildcards if necessary
if Rtrim(#FirstName) <> ''
begin
If(Len(#FirstName) < 30) and (CharIndex('%', #FirstName) = 0) and #FirstName != ''
Set #FirstName = char(39) + #FirstName + '%' + char(39)
end
if Rtrim(#LastName) <> ''
begin
If(Len(#LastName) < 60) and (CharIndex('%', #LastName) = 0) and #LastName != ''
Set #LastName = Char(39) + #LastName + '%' + char(39)
end
Now build dinamically the filter base on input parameters
if Rtrim(#LastName) <> ''
select #Where = #Where + ' and a.LastName like '+ Rtrim(#LastName)
You need to escape the apostrophe in the input string (basically replace a single ' with two '') as you build your SQL string
You need to pay attention to this anywhere you choose to pass user input to a SQL server database as its a security issue (SQL Injection Attacks) c.f. Bobby Tables
if Rtrim(#LastName) <> ''
select #Where = #Where + ' and a.LastName like '+ Replace(Rtrim(#LastName),'''','''''') + ''
My suggestion is to write the query to contain an alternate column to be used for filtering with the apostrophe/single quote replaced by any special character such as a #. This allows you to leave the original column intact in case you want to display it.
To do that in SQL Server, you could do something like this:
Select
tbl.strName_Last,
REPLACE(tblOrder.strName_Last, '''','#')) as StrLastNameForFilter
....
Then change your code to filter based on this alternate column, and in the user-provided filter string, replace the apostrophe/single quote with the special character.