Issue With Apostrophe - sql-server-2000

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.

Related

SQL : Getting Incorrect Syntax near '=' While using CASE statement with variables

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;

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.

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)

stored procedure for search string with firstname name

i need query which starts with first name here is my query:
if(#firstName <> '')
BEGIN
set #queryString = #queryString+ ' and UPPER(col_FirstName) like ''%' +#firstName +'%'''
END
if(#lastName <> '')
BEGIN
set #queryString = #queryString + ' and UPPER(col_LastName) like ''%' +#lastName +'%'''
but it is searching first name in middle also i want to search only with initials letters
thanks
Both masks in your constructed condition specify that the search be performed anywhere in the column value:
... + ' and UPPER(col_FirstName) like ''%' + #firstName + '%'''
...
... + ' and UPPER(col_LastName) like ''%' + #lastName + '%'''
The percent sign in the mask stands for "any number of any characters". Placed before the search term, therefore, it would match a value where the search term (#firstName) is preceded by any number of characters. To specify that the col_FirstName value should start with the #firstName value (and possibly have an arbitrary number of characters afterwards), just remove the leading percent, i.e. like this:
... + ' and UPPER(col_FirstName) like ''' + #firstName + '%'''
Insted of these IFs you can do it in one query like so:
...
WHERE ...
AND (#lastName <> '' OR UPPER(col_LastName LIKE '%#lastName%')
AND (#firstName <> '' OR UPPER(col_FirstName LIKE '%#firstName%')

Convert search from SQL Server to MySQL

i need to convert this one from SQL Server into MySQL
IF IsNull(#SearchText, '') <> '' BEGIN
SET #SearchText = '%' + #SearchText + '%'
SELECT NewsID,DeptID,DeptName,Title,Details ,NewsDate,img
FROM #tbSearchtextTb
WHERE IsNull(Title,'')+IsNull(Details,'') LIKE #SearchText END
this code will search fro my search word in this columns: Title, Details.
i tried to convert this line but i had lots of errors:
these are my unsuccessful attempts
IF ISNULL(SearchText,'') <> '' THEN
SELECT CatID,CatTitle,CatDescription,CatTitleAr,CatDescriptionAr,PictureID,Published,DisplayOrder,CreatedOn
FROM tmp
WHERE CatTitle + CatDescription + CatTitleAr + CatDescriptionAr
LIKE $SearchText;
and this one
IF $SearchText IS NOT NULL THEN
SELECT CatID,CatTitle,CatDescription,CatTitleAr,CatDescriptionAr,PictureID,Published,DisplayOrder,CreatedOn
FROM tmp
WHERE ISNULL(CatTitle,'') +ISNULL(CatDescription ,'') +ISNULL(CatTitleAr ,'') +ISNULL(CatDescriptionAr,'') LIKE $SearchText;
and many many other ways but i could not find any.
so if you know please let me know, thanks and best regards.
you can use fulltext search in mysql
http://dev.mysql.com/doc/refman/5.5/en/fulltext-search.html
The SQL Server version can also be written:
IF #SearchText <> '' -- null is implicitly <> ''
BEGIN
SELECT NewsID,DeptID,DeptName,Title,Details ,NewsDate,img
FROM #tbSearchtextTb
WHERE IsNull(Title,'')+IsNull(Details,'') LIKE '%' + #SearchText + '%'
END
IsNull is IFNull in MySQL.
Strings are joined using Concat in MySQL
Nulls are implicitly '' in concat
IF SearchText <> '' THEN # << again, this test is sufficient
SELECT
CatID,CatTitle,CatDescription,CatTitleAr,CatDescriptionAr,
PictureID,Published,DisplayOrder,CreatedOn
FROM tmp
WHERE Concat(CatTitle, CatDescription, CatTitleAr, CatDescriptionAr)
LIKE Concat('%',$SearchText,'%');