sql-server - 在 OpenQuery 中执行存储过程我缺少什么
问题描述
我正在尝试使用 OpenQuery 将数据插入临时表。OpenQuery 假设执行一个输出数百行的存储过程。
为了不定义Create Table #temp1
,我正在尝试执行 OpenQuery 并在查询#temp1
中使用 into 语句将结果插入表中。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, '+ @concateCommand +') oq'
EXEC (@opQuery);
错误信息:
消息 102,级别 15,状态 1,第 20 行“2020”附近的语法不正确。
如果我尝试以以下格式执行
Select * Into #Temp1 from Openquery(LOCALSERVER, 'EXEC dbo.getRecordsByOrderDate ''2020-12-11'',''''2020-12-12''''') oq
消息 11529,级别 16,状态 1,过程 sys.sp_describe_first_result_set,第 1 行 [批处理开始第 31 行] 无法确定元数据,因为每个代码路径都会导致错误;请参阅之前的一些错误。
消息 2812,级别 16,状态 62,过程 sys.sp_describe_first_result_set,第 1 行 [批处理开始第 31 行] 找不到存储过程 'dbo.getRecordsByOrderDate'。
解决方案
问题是您缺乏对注入参数的引号进行转义。调试动态代码最简单的方法是PRINT
/ SELECT
it。如果你这样做,你会很快看到问题:
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);
注意我也更改了数据类型和样式。在 SQL Server 和数据类型中,样式yyyy-MM-dd
并不明确,因为您不需要 20 亿个字符作为日期。
但是请注意,执行此操作后,您仍然无法访问#Temp1
. 临时表仅在创建它的范围内持续存在,并且该范围是动态 SQL 的。您需要在动态语句内部使用永久表,或者CREATE
在动态语句外部使用临时表才能在其外部使用它。
推荐阅读
- php - Symfony 4 Match 方法如火种
- flutter - Flutter Audioplayers 延迟
- rest - 如何在没有资源 ID 的情况下为 GET & DELETE 正确请求 REST API?
- c# - HttpRequest.RouteValues 属性不可从代码访问,但可从调试器访问
- python - 根据条件在熊猫数据框系列上应用功能
- html - css bootstrap 类不像我写的那样工作
- python - 为什么 Holoviz Panel 显示文本而不是 seaborn 情节?
- c# - 在动态创建的手风琴窗格内使用动态创建的按钮的点击事件
- webpack - 无法解析“puppeteer-core/lib”中的“ws”
- ios - 根据上一个按下的按钮在下一个视图控制器中显示其他数组