I am trying to use openquery to access a linked server. However, it appears to be impossible because, you cannot have the correct number of Single quotes. I need to pass a variable Start and End date, so I cannot use the basic openquery method, but instead must use the EXEC(@OPENQUERY+ @SQL) method. The problem is, to pass the date through the @SQL variable I must use ''' so it has 1 quote, but then when it gets passed to the EXEC(OPENQUERY+@SQL) the open query which introduces another level of quotes, causes the dates to now be not be quoted and I get an error. If I add another layer of quotes it then causes them to be double quotes causing that error. Is it not possible to use quotes in an open query? I have the same issue even passing things like Where Username = 'Jack'. I can never have the correct number of quotes.
DECLARE @STARTDT NVARCHAR(10) = '2019-01-01'
,@ENDDT NVARCHAR(10) = '2019-03-01'
DECLARE @SQL NVARCHAR(4000)
DECLARE @OPENQUERY nvarchar(4000)
, @LinkedServer nvarchar(4000)
SET @LinkedServer = 'ProductionSvr'
SET @SQL =
'select *
from SalesData a
where a.Sale_date between ''' + @StartDt + ''' and ''' + @ENDDT + ''')
'''
print @SQL
SET @OPENQUERY = 'SELECT * FROM OPENQUERY('+ @LinkedServer + ','''
EXEC (@OPENQUERY+@SQL)
Within a quoted string, you have to escape a single quote with an additional single quote, which is where you start to see the four and five single quotes in a row. In order to help simplify things, I would make a couple of suggestions.
First, keep your strings more segregated in their duties. Your @SQL
variable includes the necessary ending punctuation for your OPENQUERY
, but the beginning punctuation is in the @OPENQUERY
variable. (This might be clearer in the code below.)
Also, I'd recommend using proper data types (such as your dates), and then use the CONCAT
function, which conveniently handles all of the data type conversions for you.
So, the modified version of what you started with would look like this:
DECLARE @OPENQUERY nvarchar(4000)
, @LinkedServer nvarchar(256)
, @SQL NVARCHAR(4000);
--Set your dates. Use the right data type to avoid sending
--invalid dates into your query. Easier to debug them here.
DECLARE @STARTDT DATE = '2019-01-01'
,@ENDDT DATE = '2019-03-01';
--Set your server.
SET @LinkedServer = 'ProductionSvr';
--Then set up the inner query.
SET @SQL =
CONCAT(
'select *
from SalesData a
where a.Sale_date between ''', @StartDt, ''' and ''', @ENDDT,'''');
--Set up the OPENQUERY variable with all of the punctuation that it needs,
--so you just need to drop in your LinkedServer name and your SQL statment.
--Use CONCAT because it handles the data type conversions for you.
SET @OPENQUERY = CONCAT('SELECT * FROM OPENQUERY(',@LinkedServer,',''(',@SQL,')'')');
PRINT @OPENQUERY;
Result:
SELECT * FROM OPENQUERY(ProductionSvr,'(select *
from SalesData a
where a.Sale_date between '2019-01-01' and '2019-03-01')')