【问题标题】:What am I missing to execute stored procedure in OpenQuery在 OpenQuery 中执行存储过程我缺少什么
【发布时间】:2020-12-11 21:07:15
【问题描述】:

我正在尝试使用 OpenQuery 将数据插入临时表。 OpenQuery 假设执行一个输出数百行的存储过程。

为了不定义Create Table #temp1,我正在尝试执行OpenQuery,并使用Select 查询中的to 语句将结果插入#temp1 表中。我想知道是什么导致它不执行?

  1. 似乎它可能引用了未正确放置的问题。我如何获得与此相关的帮助?

  2. 我的服务器包含多个数据库(实例)。这里需要怎么定义?

我在这里提供我的查询示例

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'。

【问题讨论】:

标签: sql-server stored-procedures openquery


【解决方案1】:

问题是您没有对注入参数的引号进行转义。调试动态代码最简单的方法是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 的样式在 SQL Server 和数据类型中并不明确,因为日期不需要 20 亿个字符。


但是请注意,执行此操作后,您仍然无法访问#Temp1。临时表仅在创建它的范围内持续存在,并且该范围是动态 SQL 的。您需要在动态语句内使用永久表,或 CREATE 在动态语句外使用临时表才能在其外部使用它。

【讨论】:

  • 很好的解释。欣赏。
猜你喜欢
  • 2011-05-08
  • 1970-01-01
  • 2015-09-21
  • 2014-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多