SQL SERVER how to escape special character - sql-server-2008

I have a table that exists on a linked server and it has a field called name and I want to search a string called Macy's on that field. I am executing this as a dynamic SQL:-
declare #Sql nvarchar(2000)
declare #searchName nvarchar(255)
SET #searchName = N'macy''s'
SET #sql = 'SELECT * from crm_opportunity o where o.NAME LIKE ''% ' + #searchName + '%'' ESCAPE '''''' '
exec (#sql).
In other words I am trying to escape the single quote. I get the error Msg 102, Level 15, State 1, Line 1 Incorrect syntax near 's'.
Any ideas and suggestions!

Instead of using EXEC, use sp_executesql and parameterize your query:
execute sp_executesql
N'SELECT * from crm_opportunity o where o.NAME LIKE ''%'' + #searchName + ''%''',
N'#searchName nvarchar(255)',
#searchName = N'macy''s'
Not only does this help avoid confusing quote escaping, but it also protects you against Sql Injection attacks.

Doubling quotes escapes the character so you use it inside a string value.
exec('select * from [dbo].[UsersTbl] where and UserType = ''CLT'' ')

Related

How to concatenate strings in a Select statement in MySQL

I have to run a query in SQL Server using data from a MySQL database. When I needed to do the opposite, I found an easy way to accomplish what I needed writing an update query using the select statement in SQL Server.
In SQL Server I wrote:
SELECT 'update sgidb.Example set MySQLCol1 = ' + cast(MSSQLCol1 as varchar(max)) + ' where MySQLCol2 = ' + cast(MSSQLCol2 as varchar(max)) + ';' FROM MSSQLTable
That resulted in a bunch of update statements with the keys I needed like:
'update sgidb.Example set MySQLCol1 = 12 where MySQLCol2 = 45;
But when I tried to do the same in MySQL I got a bunch of syntax errors. The web told me MySQL don't need the + operator to concatenate strings in a sentence, but it didn't work, neither writing the concatenate function explicitly. Any ideas?
You can use the CONCAT function which is available in MySQL as well as in SQL, like this:
SELECT CONCAT('update sgidb.Example set MySQLCol1 = ' , MSSQLCol1 , ' where MySQLCol2 = ' , MSSQLCol2 , ';' )FROM MSSQLTable
Now in the above solution you need to take care of the blank space after or before or even after and before the statement.
For tackling the above situation what you can do is to use the function CONCAT_WS, which is available in MySQL as well as in SQL:
SELECT CONCAT_WS(' ', 'update sgidb.Example set MySQLCol1 =' , MSSQLCol1 , 'where MySQLCol2 =' , MSSQLCol2 , ';' )FROM MSSQLTable
CONCAT_WS function adds two or more strings together with a separator.
Now no need to take care of the spaces that you need to put to avoid the syntax error anymore.
Please note that, CONCAT_WS is going to handle null as well. But in case of CONCAT, if any of the variable/field is null then the entire CONCATENATED result becomes null.
Here's how you can do it
SELECT concat("update sgidb.Example set MySQLCol1 = ",MSSQLCol1,"where MySQLCol2 = ",MSSQLCol2,";") FROM MSSQLTable;
Both SQL Server and mysql have got CONCAT function.
You can use the below query in both RDBMS.
SELECT CONCAT('update sgidb.Example set MySQLCol1 = ' , MSSQLCol1 , ' where MySQLCol2 = ' , MSSQLCol2 , ';' )FROM MSSQLTable
You may try concat to concatenate your string.
Example as:
SELECT CONCAT('MySQL CAST example #',CAST(2 AS CHAR));
#ouput
MySQL CAST example #2
In your above update query your set and where column may have varchar, but if you closely look into your query ' is missing in both of the column names. Please try the below query.
SELECT CONCAT('update sgidb.Example set MySQLCol1 = ''',
CAST(MSSQLCol1 AS VARCHAR(MAX)),
''' where MySQLCol2 = ''',
CAST(MSSQLCol2 AS VARCHAR(MAX)) ,
''';' )
FROM MSSQLTable;

How to set into query string the Replace Statement in SQL?

This is my problem.. but i will show example to make it simpler
I have a stored proc named usp_Replace. This sp will replace quotation marks with whitespace.
This is the original query without setting it into query string..
CREATE PROCEDURE usp_Replace
#desc varchar(50)
AS
BEGIN
SET NOCOUNT ON;
SELECT '' + Replace(REPLACE(REPLACE(#desc, CHAR(13), ''), CHAR(10), ''),'"','') + ''
END
but..
I want to set the select statement into query string because for some reason I will have to use condition statement but will not show it as it is not part of the problem.
Here..
ALTER PROCEDURE usp_Replace
#desc varchar(50)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #query nvarchar(max)
DECLARE #condition nvarchar(max)
SET #condition = null
SET #query = ' SELECT '' + Replace(REPLACE(REPLACE('''+#desc+''', CHAR(13), ''), CHAR(10), ''),''"'','') + '' '
SET #query = #query + ISNULL(#condition,'')
EXEC sp_executesql #query
END
I'm getting error on this, resulting that there is unclosed quotation marks.
I'm really having problem with how and where to put single quotation marks.
Please help, if you have encountered this problem or any links/suggestions. I will be glad to learn about it. Thanks.
You need to quote all the single in the string, including the empty string. So, '' becomes '''':
SET #query = 'SELECT Replace(REPLACE(REPLACE(#desc, CHAR(13), ''''), CHAR(10), ''''),'' " '', '''') '
I'm not sure what the empty strings were doing at the beginning and end, so I just removed them.

Creating a dynamic where clause in SQL Server stored procedure

I am trying to create a stored that will accept two values, a column name and a value. It will then check if there is a record that exists for the passed in column name with the passed in value. I've tried the following
CREATE PROCEDURE p_HasActiveReference
#pi_colName varchar(100)
,#pi_colValue varchar(100)
AS
BEGIN
SET NOCOUNT ON
declare #sql varchar(1000)
set #sql = 'IF EXISTS(SELECT TOP 1 p.PaymentId
FROM Payments p
WHERE ' + #pi_colName + ' = ' + #pi_colValue + 'AND Active = 1)
SELECT ''True'' AS RETVAL
ELSE
SELECT ''False'' AS RETVAL'
exec(#sql)
END
However, I always get this error
Conversion failed when converting the varchar value 'InternalOr' to data type int.
When I call the procedure with the following
p_HasActiveReference 'InternalOrgCode', '10110'
The internalOrgCode column is of value varchar(10)
I am not a SQL expert, so I am not even sure if what I need to achieve is even possible using that technique!
Thanks!
At least one issue: you should be surrounding your string value with single quotes, and to escape those inside a string you need to double them up:
WHERE ' + #pi_colName + ' = ''' + #pi_colValue + ''' AND ...
You also may want to declare your #sql variable as something bigger than 100 characters! Looks like your string is getting truncated.
If the possible values for #pi_colName are finite, the data type is always string, and the columns are collation compatible, you could do something like this and avoid dynamic SQL:
SELECT ...
WHERE CASE #pi_colName
WHEN 'col1' THEN col1
WHEN 'col2' THEN col2
END = #pi_ColValue;

copy entire row (without knowing field names)

Using SQL Server 2008, I would like to duplicate one row of a table, without knowing the field names. My key issue: as the table grows and mutates over time, I would like this copy-script to keep working, without me having to write out 30+ ever-changing fields, ugh.
Also at issue, of course, is IDENTITY fields cannot be copied.
My code below does work, but I wonder if there's a more appropriate method than my thrown-together text string SQL statement?
So thank you in advance. Here's my (yes, working) code - I welcome suggestions on improving it.
Todd
alter procedure spEventCopy
#EventID int
as
begin
-- VARS...
declare #SQL varchar(8000)
-- LIST ALL FIELDS (*EXCLUDE* IDENTITY FIELDS).
-- USE [BRACKETS] FOR ANY SILLY FIELD-NAMES WITH SPACES, OR RESERVED WORDS...
select #SQL = coalesce(#SQL + ', ', '') + '[' + column_name + ']'
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = 'EventsTable'
and COLUMNPROPERTY(OBJECT_ID('EventsTable'), COLUMN_NAME, 'IsIdentity') = 0
-- FINISH SQL COPY STATEMENT...
set #SQL = 'insert into EventsTable '
+ ' select ' + #SQL
+ ' from EventsTable '
+ ' where EventID = ' + ltrim(str(#EventID))
-- COPY ROW...
exec(#SQL)
-- REMEMBER NEW ID...
set #EventID = ##IDENTITY
-- (do other stuff here)
-- DONE...
-- JUST FOR KICKS, RETURN THE SQL STATEMENT SO I CAN REVIEW IT IF I WISH...
select EventID = #EventID, SQL = #SQL
end
No, there isn't any magic way to say "SELECT all columns except <foo>" - the way you're doing it is how you'll have to do it (the hack in the other answer aside).
Here is how I would alter your code, with these changes (some are hyperlinked so you can read my opinion about why):
use sys.columns over INFORMATION_SCHEMA.COLUMNS
use nvarchar instead of varchar
use scope_identity instead of ##identity
use sp_executesql instead of exec
use stuff instead of coalesce
use SET NOCOUNT ON
add semi-colons
use the schema prefix
use QUOTENAME since it's safer than '[' + ... + ']'
ALTER PROCEDURE dbo.spEventCopy
#EventID INT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #sql NVARCHAR(MAX) = N'';
SELECT #sql += ',' + QUOTENAME(name)
FROM sys.columns
WHERE [object_id] = OBJECT_ID('dbo.EventsTable')
AND is_identity = 0;
SET #sql = STUFF(#sql, 1, 1, '');
SET #sql = N'INSERT dbo.EventsTable(' + #sql + ')
SELECT ' + #sql + ' FROM dbo.EventsTable
WHERE EventID = ' + CONVERT(VARCHAR(12), #EventID) + ';';
EXEC sp_executesql #sql;
SELECT #EventID = SCOPE_IDENTITY();
-- do stuff with the new row here
SELECT EventID = #EventID, SQL = #SQL;
END
If you know the what your identity column is called (and it won't be the column changing), you could do this:
SELECT * INTO #dummy FROM EventsTable where EventID = #EventID;
ALTER TABLE #dummy
DROP COLUMN MyIdentityColumn
INSERT EventsTable SELECT * FROM #dummy
DROP TABLE #dummy
Since a table can only every have one identity column, specifying that in the query shouldn't limit you too much.
As Aaron Bertrand points out, there are risks associated with this approach. Please read the discussion in the comments below.

What is best method to read a column value having quote ' and insert into a different table?

Hey I have a name column in my table, suppose i get have name O'Neil, when ever i read this name and insert into a linked server throught dynamic SQL I get error...How to handle this...
One method is to check if my name has a quote(') but I am researching if someone coul
my dynamic SQL looks like
'name = '+#quote+#name+#quote
#quote is nothing but below...
set #quote = ''''
thanks,
Naga
I guess you problem could be demonstrated with this code:
declare #Name varchar(20)
set #Name = 'O''Neil'
declare #SQL nvarchar(100)
set #SQL = 'select '+#Name
exec (#SQL)
Result: Unclosed quotation mark after the character string 'Neil'.
You can use quotename to properly add quote characters:
set #SQL = 'select '+quotename(#Name, '''')
The better alternative is to use sp_executesql and pass #Name as a parameter.
set #SQL = 'select #Name'
exec sp_executesql #SQL, N'#Name varchar(20)', #Name
If you can use PreparedStatements then this is better way of inserting/updating many rows. Such code in Jython (using Javas JDBC) looks like:
db = DriverManager.getConnection(jdbc_url, usr, passwd)
pstm = db.prepareStatement("insert into test (lastname) values (?)")
pstm.setString(1, "O'Neil")
reccnt = pstm.execute()
You will find similar PreparedStatement in ODBC, .net etc. It should be much lighter for database for massive inserts then creating full SQL insert statement for every inserted value.
Such massive insert from CSV file can look like:
pstm = db.prepareStatement("insert into test (lastname) values (?)")
while not csvfile.eof():
lastname = csvfile.next_line()[0]
pstm.setString(1, lastname)
reccnt = pstm.execute()