I have the following query, executed with OPENQUERY :
DECLARE #DOMAIN NVARCHAR = N'XXX'
DECLARE #QUERY NVARCHAR(MAX)= '
SELECT * FROM OPENQUERY( [XX\XX],''
SELECT CONCAT(CONCAT([Firstname],''),[Lastname]) AS [Owner]
FROM [Employee] '')'
EXECUTE XX_executesql #QUERY
When I execute , I get this following error :
Msg 102, Level 15, State 1, Line 4 Incorrect syntax near ')'. Msg 105,
Level 15, State 1, Line 5 Unclosed quotation mark after the character
string ')'.
If you print the #Query value, you will see the error root. So if you run the following code:
DECLARE #DOMAIN NVARCHAR = N'XXX';
DECLARE #QUERY NVARCHAR(MAX)= '
SELECT * FROM OPENQUERY( [XX\XX],''
SELECT CONCAT(CONCAT([Firstname],''),[Lastname]) AS [Owner]
FROM [XXX].[dbo].[Employee] '')'
PRINT #QUERY
You will get the following result:
SELECT * FROM OPENQUERY( [XX\XX],'
SELECT CONCAT(CONCAT([Firstname],'),[Lastname]) AS [Owner]
FROM [XXX].[dbo].[Employee] ')
Now it is clear why SQL Server returns the
Unclosed quotation mark after..
To solve it you need to keep in mind that, in order to have a single quote mark in the output in a string variable, you need to put two single quote mark.
Now you need to rewrite it as below:
DECLARE #DOMAIN NVARCHAR = N'XXX';
DECLARE #QUERY NVARCHAR(MAX)= '
SELECT * FROM OPENQUERY( [XX\XX],''
SELECT CONCAT(CONCAT([Firstname],''''),[Lastname]) AS [Owner]
FROM [XXX].[dbo].[Employee] '')'
PRINT #QUERY
aforementioned query will produce:
SELECT * FROM OPENQUERY( [XX\XX],'
SELECT CONCAT(CONCAT([Firstname],''),[Lastname]) AS [Owner]
FROM [XXX].[dbo].[Employee] ')
You can now simply replace Print with EXECUTE command and execute it!
You are not escaping your string quotes.
If you want to include an ' inside an string, you have to write it twice ''
So, for example, CONCAT([Firstname],'') would have to be CONCAT([Firstname],'''')
See How do I escape a single quote in SQL Server?
PS: And as #TT. has commented, in this case you will probably need to re-escape your quotes inside the openquery scope, because the openquery call will escape them again.
So CONCAT([Firstname],'') would in fact have to be CONCAT([Firstname],'''''''')
Related
Can someone please explain to me what is wrong with the below expression. I believe that's I'm converting my date correctly using CONVERT 126 and that my quotes are escaped correctly using char 39 but I could be wrong.
T-SQL:
DECLARE #end2 DATETIME2 = GETDATE();
DECLARE #test2 nvarchar(200) = N'SELECT * FROM OPENQUERY(x, '
+ char(39) + 'SELECT OBJID FROM SALE WHERE MODIFIED >= '
+ CHAR(39) + CONVERT(nvarchar(24),#end2,126)
+ char(39) + char(39) + ')';
PRINT #test2;
EXEC (#test2);
Print output:
select * from openquery(x, 'SELECT OBJID FROM SALE
WHERE MODIFIED >= '2023-01-19T11:55:21.1233'')
Error:
Msg 102, Level 15, State 1
Incorrect syntax near '2023'.
Tried different formats, casting, etc. I can't use EXEC x..sys.sp_executesql because x is Firebird, not another SQL Server.
You can escape the ' character with another one, i.e. ''. But you need to double escape it, i.e. your final string needs to have double single quotes in to be escaped in your dynamic SQL, which means a lot of escaping, i.e.
DECLARE #end2 DATETIME2
set #end2 = getdate()
declare #test2 nvarchar(200)
set #test2 = 'select * from openquery(x, ''SELECT OBJID FROM SALE WHERE MODIFIED >= '''''+convert(nvarchar(24),#end2,126)+''''''')'
print #test2
exec (#test2)
Which results in:
select *
from openquery(x, 'SELECT OBJID FROM SALE WHERE MODIFIED >= ''2023-01-19T18:06:22.6033''')
I am dynamically building a SQL statement based on operations from a couple of different tables. The salient part of the SQL is below.
DECLARE #SQL NVARCHAR(MAX) = NULL
...
SELECT #sql = 'TRIM(CAST(' + STRING_AGG(EXPORT_COL, ' AS VARCHAR)) + '','' + TRIM(CAST(') FROM #TEMP_TABLE
SET #sql = 'SELECT''(''+'+#sql+' AS VARCHAR))+'')'''+'FROM '+'[mydatabase].[dbo].['+#TABLENAME+']'
SET #sql = REPLACE(#sql,'''','''''')
When I call the code using sp_executesql
EXEC sp_executesql #sql
I get this error
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near ''
If I query #sql or print the value to the messages window in SSMS I get:
SELECT''(''+TRIM(CAST(COL1 AS VARCHAR)) + '','' + TRIM(CAST(COL2 AS VARCHAR))+'')''FROM [mydatabase].[dbo].[DATA_TABLE]
which is the output I would expect.
Copying the text and calling sp_executesql using a quoted version of the output string, the query succeeds with no error.
EXEC sp_executesql N'SELECT''(''+TRIM(CAST(COL1 AS VARCHAR)) + '','' + TRIM(CAST(COL2 AS VARCHAR))+'')''FROM [mydatabase].[dbo].[DATA_TABLE]'
I have already checked for the presence of non-printable characters as indicated in this post
I have also implemented a function that "should" strip out any non printable characters per this post. Yet the problem persists.
SQL Server 2017 Express (v14.0.1000.169) on Windows Server 2019 standard.
You need to be really careful about when and what parts need single quotes vs which parts need doubled quotes.
If you are writing the string to assign it to a variable, it needs the doubled quotes. If, however, the string already has the quote inside, it doesn't need to be doubled again.
Here's a simplified example showing the issues/approach
CREATE TABLE #Test (TestVal varchar(100));
INSERT INTO #Test (TestVal) VALUES ('abcde');
Now, when running the process with doubled quotes (similar to yours), here are the results
DECLARE #SQL2 nvarchar(max) = 'SELECT ''''('''' + TestVal + '''')'''' FROM #Test;'
PRINT #SQL2;
/* -- Result
SELECT ''('' + TestVal + '')'' FROM #Test;
*/
EXEC sp_executesql #SQL2;
/* -- Result
Msg 102, Level 15, State 1, Line 12
Incorrect syntax near ''.
*/
EXEC sp_executesql N'SELECT ''('' + TestVal + '')'' FROM #Test;';
/* -- Result
(abcde)
*/
Note that in the bottom command, the doubled quotes were needed so that the string would contain single quotes - and therefore works. However, when already in the string, it made the command fail.
Now, if we make the variable just have single quotes, it works
DECLARE #SQL3 nvarchar(max) = 'SELECT ''('' + TestVal + '')'' FROM #Test;'
PRINT #SQL3;
/* -- Result
SELECT '(' + TestVal + ')' FROM #Test;
*/
EXEC sp_executesql #SQL3;
/* -- Result
(abcde)
*/
Statement:
declare #Searchkey varchar(50)='a'
declare #Sql nvarchar(max) =''
set #Sql = #Sql +
'select * from products where upper(ProductName) like %' + upper(#Searchkey) + '%'
execute sp_executesql #Sql
Error message:
Msg 102 Level 15 State 1 Line 1
Incorrect syntax near 'A'.
You do not require a dynamic query for such case, you can use below simple query to get the desired result.
declare #Searchkey varchar(50)= 'a'
select * from products where upper(ProductName) like '%' + upper(#Searchkey) + '%'
If you still want to go with Dynamic query then below are the connect syntax.
declare #Searchkey varchar(50)='a'
declare #Sql nvarchar(max) =''
set #Sql =#Sql+'select * from products where upper(ProductName) like ''%' +upper(#Searchkey)+'%'''
--print #Sql
execute sp_executesql #Sql
Note: Whenever you will get an error with a dynamic query then the best way is to print the query using print statement that will help to identify the error easily. In your case, a single quote was missing.
The reason for this error is that you need to add quotes around the search pattern, when you build the dynamic statement. But I think that your should use parameter in this dynamically built statement to prevent SQL injection issues:
DECLARE #Searchkey varchar(50) = 'a'
DECLARE #Sql nvarchar(max) = N''
SET #Sql =
#Sql +
N'SELECT * FROM products WHERE UPPER(ProductName) LIKE CONCAT(''%'', UPPER(#Searchkey), ''%'')'
PRINT #Sql
EXEC sp_executesql #Sql, N'#Searchkey varchar(50)', #Searchkey
You're not placing quotes around your search term, so the literal query that's being sent is:
select * from products where upper(ProductName) like %A%
You need to wrap the search term in quotes, like so:
set #Sql =#Sql+'select * from products where upper(ProductName) like ''%'+upper(#Searchkey)+'%'''
This will create the following query:
select * from products where upper(ProductName) like '%A%'
I am new to SQL Server 2012 and have read in lots of places that we only need to escape the single-quote character, by doubling it up. In most cases this seems to work for me, but I am having particular trouble with the following simple stored procedure:
DECLARE #SQLStr nvarchar(max)
DECLARE #SQLParam nvarchar(max)
DECLARE #SQLParamValues nvarchar(max)
SET #SQLStr = 'UPDATE test_data SET name=#1,name_reservation_date=#2 WHERE id=#3'
SET #SQLParam = '#1 nvarchar(50),#2 datetime2(0),#3 bigint'
SET #SQLParamValues = '#1=N''b''1'',#2=''2014-4-25 12:09:39'',#3=12345'
EXEC( 'EXECUTE sp_executesql N''' + #SQLStr + ''', N''' + #SQLParam + ''', ' + #SQLParamValues)
The error that I am getting is this:
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '1'.
Msg 105, Level 15, State 1, Line 1
Unclosed quotation mark after the character string ',#3=12345'.
And the problem is that I am trying to write the value b'1, which I have escaped as b''1. If I write just b1 then there is no problem.
The syntax error is on the last line - i.e. when trying to use the #SQLParamValues string as an argument to my EXEC call.
But I can't see any unclosed quotation mark, can someone help me out? Is there a better approach that I should be taking, to avoid all of these doubling-up of quotes? I've inherited this system from someone else so I'm not entirely convinced at this stage.
You don't need to wrap sp_executesql in another EXEC. Use the syntax below. Note that the parameters' values are passed without a variable:
DECLARE #SQLStr nvarchar(max)
DECLARE #SQLParam nvarchar(max)
SET #SQLStr = N'UPDATE test_data SET name=#1,name_reservation_date=#2 WHERE id=#3'
SET #SQLParam = N'#1 nvarchar(50),#2 datetime2(0),#3 bigint'
EXECUTE sp_executesql #SQLStr, #SQLParam,
#1=N'b''1',#2='2014-4-25 12:09:39',#3=12345
I am trying to run a query in SQL 2008 by doing:
#query varchar(max)
SET #query = 'SELECT * FROM Table WHERE [Name] = ' 'Karl' ' '
EXEC(#query)
The problem is that for some reason the apostrophes around 'Karl' don't get escaped, i.e. the query executes as ...WHERE [Name] = Karl and fails.
Anyone has a suggestion?
There are several ways that you can escape character data in SQL Server, some people even advocate the use of the QUOTENAME() functions.
If you really want to develop of solid understanding of this subject area then may I recommend that you take a look at what experienced SQL Server Developers consider to be essential reading with regard to the different methods you can use to incorporate Dynamic T-SQL into your coding.
The Curse and Blessings of Dynamic SQL
Try:
DECLARE #query varchar(max)
SET #query = 'SELECT * FROM Table WHERE [Name] = ''Karl'''
PRINT 'when in doubt, print the query out: '+ISNULL(#query,'')
EXEC(#query)
To have a single quote appear, you need to have two adjacent single quotes. You escape a single quote with a single quote, for example:
PRINT '''' --will print a one single quote
PRINT '''''' --will print two single quotes
PRINT 'can''t' --will print can't
This works on my machine from SQL Server Management Studio:
#query varchar(max)
SET #query = 'SELECT * FROM Table WHERE [Name] = ''''''Karl'''''''
EXEC(#query)
A double single ('') quote will act like a single single quote when inside a string literal.
Have you tried using a variable?
declare #karl_name varchar(10);
set #karl_name = '''Karl''';
SELECT * FROM Table WHERE [Name] = #karl_name
do like this
SET #query = 'SELECT * FROM Table WHERE [Name] = ''''Karl'''''
This works:
create table #demo([Name] varchar(max))
insert into #demo([Name]) values('''Karl''')
insert into #demo([Name]) values('Karl')
declare #query varchar(max)
set #query = 'SELECT * FROM #demo WHERE [Name] = ''''''Karl'''''''
EXEC(#query)
Output:
'Karl'
But if 'Karl' is variable text, it's highly recommended to use something like this instead:
declare #query nvarchar(max)
declare #param varchar(max)
set #param = N'''Karl'''
set #query = N'SELECT * FROM #demo WHERE [Name] = #param'
exec sp_executesql #query, N'#param varchar(max)', #param
Simply escape the apostrophes by using the escaping bar \ like this 'SELECT * FROM Table WHERE [Name] = ' \'Karl\' ' '
Hope it helps