使用存储过程和 table 变量的动态 sql 查询
Dynamic sql query with stored procedure and table variable
我想动态调用存储过程,因为我的过程名称存储在某个地方,我还需要将该过程的结果存储到 table 变量中。因此,我不得不编写以下 sql 代码,
在下面的代码中
@tblEmailIds 是 table 变量,我想将 SP 的结果存储在其中
@tempEmailSource 是过程的名称
@tempRecipientsIdsCSV 是我的 SP 接受的第一个参数
@ObjectMasterId 是 SP 接受的第二个参数(可选)
DECLARE @tempTypeName NVARCHAR(100),
@tempTypeId INT,
@tempEmailSource NVARCHAR(100),
@tempRecipientsIdsCSV NVARCHAR(MAX),
@tempIsObjectSpecific BIT,
@sqlQuery NVARCHAR(MAX) = 'INSERT INTO @tblEmailIds '
SELECT TOP 1 @tempTypeName = NAME,
@tempTypeId = Id,
@tempEmailSource = EmailListSourceName
FROM @tbleRecipientsTypes WHERE IsEmailIdsFetched = 0
SELECT @tempRecipientsIdsCSV = SUBSTRING(
(SELECT ',' + CAST(RT.EmailRecipientId AS NVARCHAR(50))
FROM @tbleRecipientsTypes RT WHERE RT.Id = @tempTypeId
ORDER BY RT.EmailRecipientId
FOR XML PATH('')),2,200000)
SELECT @tempRecipientsIdsCSV
SET @sqlQuery = @sqlQuery + 'EXEC ' + @tempEmailSource +' ' +'''' + @tempRecipientsIdsCSV +''''
IF (@tempIsObjectSpecific = 1)
BEGIN
SET @sqlQuery = @sqlQuery + ' ' + @ObjectMasterId
END
PRINT @SQLQUERY
EXECUTE SP_EXECUTESQL
@SqlQuery,'@IdsCSV NVARCHAR(MAX) OUTPUT,
@ObjectMasterId INT = NULL OUTPUT', @tblEmailIds
我收到以下错误
Msg 214, Level 16, State 3, Procedure sp_executesql, Line 6 Procedure
expects parameter '@params' of type 'ntext/nchar/nvarchar'.
SP_EXECUTESQL
的 @params
的前缀 N
。
您还需要存储 OUTPUT
参数的结果
Declare @IdsCSV NVARCHAR(MAX),@ObjectMasterId INT = NULL
EXECUTE SP_EXECUTESQL
@SqlQuery,
N'@IdsCSV NVARCHAR(MAX) OUTPUT,@ObjectMasterId INT = NULL OUTPUT',
@IdsCSV = @IdsCSV OUTPUT,
@ObjectMasterId = @ObjectMasterId OUTPUT
这里有不少问题。
正如错误消息明确指出的那样,参数列表需要 NVARCHAR
所以只需在该字符串文字前加上 N
(正如@VR46 的回答中所述) .
Table 变量无法按照您尝试使用它们的方式工作。首先,你永远不会声明 @tblEmailIds
,但即使你声明了,table 变量的范围也是局部的,它们不能用作 OUTPUT
参数。相反,您需要创建一个本地临时 table(即 #tblEmailIds
)并执行 INSERT INTO #tblEmailIds
.
您引用了另一个尚未声明或填充的 table 变量 @tbleRecipientsTypes
。
您确实声明了 @tempIsObjectSpecific
但从未设置它,因此它将始终是 NULL
.
为什么@IdsCSV
(在sp_executesql
调用参数列表中)声明为OUTPUT
?您不仅没有传入 @tempRecipientsIdsCSV
(动态 SQL 中的 @IdsCSV
),甚至不需要作为参数,因为您直接连接 [= 的值22=] 进入动态 SQL,动态 SQL 中没有 @tempRecipientsIdsCSV
变量开始。所以从参数列表中删除@IdsCSV NVARCHAR(MAX) OUTPUT,
。
你说“@tempRecipientsIdsCSV 是我的 SP 接受的第一个参数”,但是你在代码中声明它,这应该会导致错误。
@ObjectMasterId
是什么数据类型?你说它被传递到 proc 中,我看到它被连接到动态 SQL 中,因此它需要是字符串类型(即不是 INT
中显示的 [=20] =] 参数列表)或者它需要在 CONVERT(NVARCHAR(10), @ObjectMasterId
.
如果传入的是@ObjectMasterId
,那么为什么在sp_executesql
参数列表中声明为OUTPUT
呢?但更好的问题可能是:既然你直接将它连接到动态 SQL,你为什么还要将它传递到 sp_executesql
?动态 SQL.
中没有使用 @ObjectMasterId
变量
我想动态调用存储过程,因为我的过程名称存储在某个地方,我还需要将该过程的结果存储到 table 变量中。因此,我不得不编写以下 sql 代码,
在下面的代码中 @tblEmailIds 是 table 变量,我想将 SP 的结果存储在其中 @tempEmailSource 是过程的名称 @tempRecipientsIdsCSV 是我的 SP 接受的第一个参数 @ObjectMasterId 是 SP 接受的第二个参数(可选)
DECLARE @tempTypeName NVARCHAR(100),
@tempTypeId INT,
@tempEmailSource NVARCHAR(100),
@tempRecipientsIdsCSV NVARCHAR(MAX),
@tempIsObjectSpecific BIT,
@sqlQuery NVARCHAR(MAX) = 'INSERT INTO @tblEmailIds '
SELECT TOP 1 @tempTypeName = NAME,
@tempTypeId = Id,
@tempEmailSource = EmailListSourceName
FROM @tbleRecipientsTypes WHERE IsEmailIdsFetched = 0
SELECT @tempRecipientsIdsCSV = SUBSTRING(
(SELECT ',' + CAST(RT.EmailRecipientId AS NVARCHAR(50))
FROM @tbleRecipientsTypes RT WHERE RT.Id = @tempTypeId
ORDER BY RT.EmailRecipientId
FOR XML PATH('')),2,200000)
SELECT @tempRecipientsIdsCSV
SET @sqlQuery = @sqlQuery + 'EXEC ' + @tempEmailSource +' ' +'''' + @tempRecipientsIdsCSV +''''
IF (@tempIsObjectSpecific = 1)
BEGIN
SET @sqlQuery = @sqlQuery + ' ' + @ObjectMasterId
END
PRINT @SQLQUERY
EXECUTE SP_EXECUTESQL
@SqlQuery,'@IdsCSV NVARCHAR(MAX) OUTPUT,
@ObjectMasterId INT = NULL OUTPUT', @tblEmailIds
我收到以下错误
Msg 214, Level 16, State 3, Procedure sp_executesql, Line 6 Procedure expects parameter '@params' of type 'ntext/nchar/nvarchar'.
SP_EXECUTESQL
的 @params
的前缀 N
。
您还需要存储 OUTPUT
参数的结果
Declare @IdsCSV NVARCHAR(MAX),@ObjectMasterId INT = NULL
EXECUTE SP_EXECUTESQL
@SqlQuery,
N'@IdsCSV NVARCHAR(MAX) OUTPUT,@ObjectMasterId INT = NULL OUTPUT',
@IdsCSV = @IdsCSV OUTPUT,
@ObjectMasterId = @ObjectMasterId OUTPUT
这里有不少问题。
正如错误消息明确指出的那样,参数列表需要
NVARCHAR
所以只需在该字符串文字前加上N
(正如@VR46 的回答中所述) .Table 变量无法按照您尝试使用它们的方式工作。首先,你永远不会声明
@tblEmailIds
,但即使你声明了,table 变量的范围也是局部的,它们不能用作OUTPUT
参数。相反,您需要创建一个本地临时 table(即#tblEmailIds
)并执行INSERT INTO #tblEmailIds
.您引用了另一个尚未声明或填充的 table 变量
@tbleRecipientsTypes
。您确实声明了
@tempIsObjectSpecific
但从未设置它,因此它将始终是NULL
.为什么
@IdsCSV
(在sp_executesql
调用参数列表中)声明为OUTPUT
?您不仅没有传入@tempRecipientsIdsCSV
(动态 SQL 中的@IdsCSV
),甚至不需要作为参数,因为您直接连接 [= 的值22=] 进入动态 SQL,动态 SQL 中没有@tempRecipientsIdsCSV
变量开始。所以从参数列表中删除@IdsCSV NVARCHAR(MAX) OUTPUT,
。你说“@tempRecipientsIdsCSV 是我的 SP 接受的第一个参数”,但是你在代码中声明它,这应该会导致错误。
@ObjectMasterId
是什么数据类型?你说它被传递到 proc 中,我看到它被连接到动态 SQL 中,因此它需要是字符串类型(即不是INT
中显示的 [=20] =] 参数列表)或者它需要在CONVERT(NVARCHAR(10), @ObjectMasterId
.如果传入的是
@ObjectMasterId
,那么为什么在sp_executesql
参数列表中声明为OUTPUT
呢?但更好的问题可能是:既然你直接将它连接到动态 SQL,你为什么还要将它传递到sp_executesql
?动态 SQL. 中没有使用
@ObjectMasterId
变量