0

I am trying to use OpenQuery to insert data into a temporary table. OpenQuery suppose to execute a stored procedure that outputs hundreds of rows.

In order to not to defining Create Table #temp1, I am trying to execute OpenQuery and inserting the result into #temp1 table using into statement in Select query. I would like to know what is causing it not to execute?

  1. It seems like it may quotes issue which is not placed correctly. How can I get help related to this?

  2. My server contains multiple databases (instances). How do I need to define it here?

I am providing an example here of my query here

DECLARE @startDate DATETIME = CONVERT(DATE, GETDATE());
DECLARE @endDate DATETIME = CONVERT(DATE, GETDATE()+1);

DECLARE @stDate NVARCHAR(MAX) = CHAR(39) + CONVERT(NVARCHAR(255), @startDate, 23)+ CHAR(39) + ',';
DECLARE @enDate NVARCHAR(MAX) = CHAR(39) + CONVERT(NVARCHAR(255), @endDate, 23) + CHAR(39);
DECLARE @execCommand NVARCHAR(MAX) = CHAR(39) + 'EXEC dbo.getRecordsByOrderDate ' ;
DECLARE @concatCommand NVARCHAR(MAX) = @execCommand + @stDate + @enDate + CHAR(39);

DECLARE @opQuery Nvarchar(MAX) = 'Select * Into #Temp1 from Openquery(LOCALSERVER, '+ @concateCommand +') oq'

EXEC (@opQuery);

Error Message:

Msg 102, Level 15, State 1, Line 20 Incorrect syntax near '2020'.

If I try to execute in below format

Select * Into #Temp1 from Openquery(LOCALSERVER, 'EXEC dbo.getRecordsByOrderDate ''2020-12-11'',''''2020-12-12''''') oq

Msg 11529, Level 16, State 1, Procedure sys.sp_describe_first_result_set, Line 1 [Batch Start Line 31] The metadata could not be determined because every code path results in an error; see previous errors for some of these.

Msg 2812, Level 16, State 62, Procedure sys.sp_describe_first_result_set, Line 1 [Batch Start Line 31] Could not find stored procedure 'dbo.getRecordsByOrderDate'.

user1413
  • 527
  • 4
  • 21
  • this may be your issue: https://stackoverflow.com/questions/2917728/t-sql-dynamic-sql-and-temp-tables – Jeremy Dec 11 '20 at 21:11
  • Why do you say it doesn't execute? – Thom A Dec 11 '20 at 21:13
  • @Larnu Please check my error message – user1413 Dec 11 '20 at 21:24
  • @Jeremy: In-Order to not to define `CREATE TABLE ` I have used `INTO` statement. – user1413 Dec 11 '20 at 21:27
  • *"Incorrect syntax near '2020'."* `2020` isn't in your code, nor does it have 20 lines; that error isn't in the SQL above, it's in something *else*. It's the Procedure that's erroring not the code above... – Thom A Dec 11 '20 at 21:27
  • there will be a scoping issue. if you define a temp table inside dynamically executed SQL, then the outer stored procedure will not be able to reference the table. – Jeremy Dec 11 '20 at 21:29
  • ... I see the problem, it's the injection of your parameters... If you `PRINT` the value of `@concatCommand` you'll see your parameters aren't properly quoted, as they are a literal string **inside** a literal string. The quotes are escaping the value outer string; there needs to be 2 single quotes, not one. – Thom A Dec 11 '20 at 21:30
  • @Larnu based on you above comment. "2020" comes from a variable `@startDate` and `@endDate` decalred on first line. Now line 20, my SSMS tab have multiple lines of SQL Query out ot this I am sharing only that is needed to post here. So line varies – user1413 Dec 11 '20 at 21:31
  • @Larnu With all due respect Sir, I removed that so that I am not hurting anyone. – user1413 Dec 11 '20 at 21:36
  • @Larnu Many apologies I wasn't meant in that sense. – user1413 Dec 11 '20 at 21:51
  • 1
    as always, I have topost the bible on dynamic SQL. http://www.sommarskog.se/dynamic_sql.html – Jeremy Dec 11 '20 at 22:01

1 Answers1

2

The problem is your lack of escapting the quotes on your injected parameters. The simplest way to debug dynamic code is to PRINT/SELECT it. If you do that you'll quickly see the problem:

DECLARE @startDate DATETIME = CONVERT(DATE, GETDATE());
DECLARE @endDate DATETIME = CONVERT(DATE, GETDATE()+1);

DECLARE @stDate NVARCHAR(MAX) = CHAR(39) + CONVERT(NVARCHAR(255), @startDate, 23)+ CHAR(39) + ',';
DECLARE @enDate NVARCHAR(MAX) = CHAR(39) + CONVERT(NVARCHAR(255), @endDate, 23) + CHAR(39);
DECLARE @execCommand NVARCHAR(MAX) = CHAR(39) + 'EXEC dbo.getRecordsByOrderDate ' ;
DECLARE @concatCommand NVARCHAR(MAX) = @execCommand + @stDate + @enDate + CHAR(39);

DECLARE @opQuery Nvarchar(MAX) = 'Select * Into #Temp1 from Openquery(LOCALSERVER, '+ @concatCommand +') oq'

PRINT @opQuery;

Which returns...

Select *
Into #Temp1
from Openquery(LOCALSERVER, 'EXEC dbo.getRecordsByOrderDate '2020-12-11','2020-12-12'') oq

Voila your first parameter escapes the second parameter, and thus the error. (I Have added additional lines, as SO's choice of "prettifier" thinks # is a comment character in SQL, and I want the escaping to be highlighted in the colouring.)

When using single quotes inside a literal string, you need to escape them by "doubly them up" (''). Thus the final statement needs to me the below:

Select *
Into #Temp1
from Openquery(LOCALSERVER, 'EXEC dbo.getRecordsByOrderDate ''20201211'',''20201212''') oq

(Additional lines added for presentation again.)

So you need to fix the definitions of your 2 injected values:

DECLARE @stDate NVARCHAR(8) = CHAR(39) + CHAR(39) + CONVERT(NVARCHAR(8), @startDate, 112)+ CHAR(39) + CHAR(39) + ',';
DECLARE @enDate NVARCHAR(8) = CHAR(39) + CHAR(39) + CONVERT(NVARCHAR(8), @endDate, 112) + CHAR(39) + CHAR(39);

Note I change the data types and styles too. The style as yyyy-MM-dd isn't unambiguous in SQL Server, and the data types, as you don't need 2 billion characters for a date.


Note, however, that after executing this you still won't be able to access #Temp1. A temporary table only persists for the scope it was created in, and that scope is the dynamic SQL's. You'll need to use a permanent table inside the dynamic statement, or CREATE a temporary table outside of the dynamic statement to use it outside of it.

Thom A
  • 88,727
  • 11
  • 45
  • 75