我试图使用OpenQuery将数据插入到临时表中。OpenQuery假设执行一个输出数百行的存储过程。
为了不定义Create Table #temp1
,我尝试执行OpenQuery并使用Select
查询中的into语句将结果插入到#temp1
表中。我想知道是什么原因导致它不执行?
,
我在这里提供一个查询的例子
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);
错误消息:
Msg 102,级别15,状态1,第20行语法不正确,接近'2020‘。
如果我尝试以以下格式执行
Select * Into #Temp1 from Openquery(LOCALSERVER, 'EXEC dbo.getRecordsByOrderDate ''2020-12-11'',''''2020-12-12''''') oq
Msg 11529、级别16、状态1、过程sys.sp_describe_first_result_set、第1批开始行31行元数据无法确定,因为每个代码路径都会导致错误;请参阅前面的错误。Msg 2812,级别16,状态62,过程sys.sp_describe_first_result_set,第1行批开始行31无法找到存储过程'dbo.getRecordsByOrderDate'.
发布于 2020-12-11 13:39:07
问题在于你没有转义注入参数的引号。调试动态代码的最简单方法是PRINT
/SELECT
。如果你这样做,你很快就会发现问题所在:
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;
还会回来..。
Select *
Into #Temp1
from Openquery(LOCALSERVER, 'EXEC dbo.getRecordsByOrderDate '2020-12-11','2020-12-12'') oq
瞧,您的第一个参数转义了第二个参数,因此出现了错误。(我增加了额外的行,因为SO对“漂亮词”的选择认为#
是SQL中的一个注释字符,我希望在着色中突出显示转义。)
当在文字字符串中使用单引号时,需要通过“加倍它们向上”(''
)来转义它们。因此,我需要在最后发言如下:
Select *
Into #Temp1
from Openquery(LOCALSERVER, 'EXEC dbo.getRecordsByOrderDate ''20201211'',''20201212''') oq
(再次添加用于表示的其他行。)
因此,您需要修复2个注入值的定义:
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);
注:我也更改了数据类型和样式。作为yyyy-MM-dd
的样式在Server和数据类型中并不是明确的,因为一个日期不需要20亿个字符。
但是,请注意,在执行此操作之后,您仍然无法访问#Temp1
。临时表只对其创建的作用域持续存在,而该作用域是动态SQL的。您需要在动态语句中使用一个永久表,或者在动态语句之外使用一个临时表以在其外部使用它。
https://stackoverflow.com/questions/65258603
复制