抛开使用动态SQL的注意事项,我想知道是否可以动态声明我想从动态SQL语句中分配给定输出变量的值的哪个局部变量。
我希望我说的够好。这里有一些代码和我遇到麻烦的地方。我有一个包含许多OUTPUT参数的存储过程,如下所示:
ALTER PROCEDURE [dbo].[mngi_psi_paginate]
@image_desc_1 VARCHAR(50) OUTPUT
,@image_desc_2 VARCHAR(50) OUTPUT
,@image_desc_3 VARCHAR(50) OUTPUT
,@image_desc_4 VARCHAR(50) OUTPUT
,@image_desc_5 VARCHAR(50) OUTPUT
,@image_desc_6 VARCHAR(50) OUTPUT
,@image_desc_7 VARCHAR(50) OUTPUT
,@image_desc_8 VARCHAR(50) OUTPUT
,@image_desc_9 VARCHAR(50) OUTPUT
,@image_desc_10 VARCHAR(50) OUTPUT
...
总共有40个OUTPUT参数。我将允许用户分页浏览未知数量的图像,一次10个图像。对于每个图像,我需要4个数据字段,但一次可能有10个记录,我宁愿不对所有40个变量赋值进行硬编码。
我意识到应该有更好的方法来实现这一点,但是接收应用程序不是Web浏览器,所以不幸的是,这是我必须使用的。
我还做了一些其他事情:确定图像总数,页数以及页面上显示的图像数量。
一旦我弄清楚给定页面上属于哪一组图像,我就将它们放入临时表中。
CREATE TABLE #images_page
(primary_key INT IDENTITY(1,1) NOT NULL
,image_id VARCHAR(36)
,image_path VARCHAR(400)
,image_type VARCHAR(5)
,image_desc VARCHAR(MAX)
)
INSERT INTO #images_page
SELECT image_id
,image_path
,image_type
,image_desc
FROM @images_set
WHERE primary_key >= @image_start
AND primary_key <= @image_end
然后我构建一个字符串来执行动态SQL语句,该语句全部包含在WHILE循环中,希望能够仅分配具有相应记录的变量(例如,@ image_desc_1从行中获取数据# 1,@ image_desc_2从行#等获取数据
SELECT @image_page_total = COUNT(*)
FROM #images_page
DECLARE @row_counter INT
,@loop_counter INT
SET @loop_counter = @image_page_total
SET @row_counter = 1
WHILE
@loop_counter > 0
AND @row_counter <= @loop_counter
BEGIN
-- Dynamically assign variables
DECLARE @sql NVARCHAR(MAX)
DECLARE @params NVARCHAR(MAX)
DECLARE @assign NVARCHAR(MAX)
SELECT @sql = 'SELECT @image_desc = image_desc ' +
'@image_path = image_path,' +
'@image_type = image_type,' +
'@image_comments = image_comments' +
'FROM #images_page ' +
'WHERE primary_key = ' + CAST(@row_counter AS VARCHAR)
SELECT @params = '@image_desc varchar(50) OUTPUT'
SELECT @assign = '@image_desc = @image_desc_' + CAST(@row_counter AS VARCHAR) + ' OUTPUT'
--This line works because I've simply typed out the variable name
EXEC sp_executesql @sql, @params, @image_desc = @image_desc_1 OUTPUT
--This line does not work because I am trying to append the '_1' to @image_desc
EXEC sp_executesql @sql, @params, @assign
SET @row_counter = @row_counter + 1
END
第一个EXEC sp_executesql行正常工作,因为这是它应该工作的方式,这就是你在所有文档和示例中看到它的方式。第二个EXEC sp_executesql是我真正希望能够做到的,但我似乎无法看到它的方法。
有没有办法以我尝试的方式实现这一目标?
我愿意接受不需要硬编码变量赋值的替代方法。
提前感谢您的任何帮助!
答案 0 :(得分:2)
我认为你的需要完全不可能,但也许这会引导你朝着正确的方向前进。它没有完全删除契约来引用所有40个变量代码,但是你不必对变量赋值进行硬编码。
我用过自己的例子。我根据@I的值设置@ T1或@ T2的值。因此,如果@I = 1,那么@ T1将被设置为'SET AT RUNTIME'。如果@I = 2,那么@ T2将被设置为'SET AT RUNTIME'。您需要将所有40个变量传递给动态查询。
DECLARE @T1 INT,
@T2 INT,
@I VARCHAR(10) = '2',
@SQL NVARCHAR(MAX);
SET @SQL = 'SET @T' + @I + ' = ''SET AT RUNTIME'''
EXEC sp_executesql @SQL, N'@T1 INT OUT, @T2 INT OUT', @T1 OUT, @T2 OUT
SELECT @T1, @T2
希望有所帮助
答案 1 :(得分:0)
似乎Spock是正确的,我无法动态计算我想从动态SQL传递出来的变量。如果我错了,请有人纠正我。
由于我只处理了10组变量,所以我把它搞砸了,然后为每一个写了一个IF语句。再说一次,如果有人有更好的选择,我会对任何事情持开放态度。
为了记录,这是我所做的,这是有效的:
SET @loop_counter = @image_page_total
SET @row_counter = 1
WHILE
@loop_counter > 0
AND @row_counter <= @loop_counter
BEGIN
-- Dynamically assign variables
DECLARE @sql NVARCHAR(MAX)
DECLARE @params NVARCHAR(MAX)
DECLARE @assign NVARCHAR(MAX)
SELECT @sql = 'SELECT @image_path = image_path, ' +
'@image_type = image_type, ' +
'@image_desc = image_desc, ' +
'@image_comments = image_comments ' +
'FROM #images_page ' +
'WHERE primary_key = ' + CAST(@row_counter AS VARCHAR)
SELECT @params = '@image_path VARCHAR(400) OUTPUT, @image_type VARCHAR(5) OUTPUT, @image_desc VARCHAR(50) OUTPUT, @image_comments VARCHAR(MAX) OUTPUT'
IF @row_counter = 1 EXEC sp_executesql @sql, @params, @image_type_1 OUTPUT, @image_type_1 OUTPUT, @image_desc_1 OUTPUT, @image_comments_1 OUTPUT
IF @row_counter = 2 EXEC sp_executesql @sql, @params, @image_type_2 OUTPUT, @image_type_2 OUTPUT, @image_desc_2 OUTPUT, @image_comments_2 OUTPUT
IF @row_counter = 3 EXEC sp_executesql @sql, @params, @image_type_3 OUTPUT, @image_type_3 OUTPUT, @image_desc_3 OUTPUT, @image_comments_3 OUTPUT
IF @row_counter = 4 EXEC sp_executesql @sql, @params, @image_type_4 OUTPUT, @image_type_4 OUTPUT, @image_desc_4 OUTPUT, @image_comments_4 OUTPUT
IF @row_counter = 5 EXEC sp_executesql @sql, @params, @image_type_5 OUTPUT, @image_type_5 OUTPUT, @image_desc_5 OUTPUT, @image_comments_5 OUTPUT
IF @row_counter = 6 EXEC sp_executesql @sql, @params, @image_type_6 OUTPUT, @image_type_6 OUTPUT, @image_desc_6 OUTPUT, @image_comments_6 OUTPUT
IF @row_counter = 7 EXEC sp_executesql @sql, @params, @image_type_7 OUTPUT, @image_type_7 OUTPUT, @image_desc_7 OUTPUT, @image_comments_7 OUTPUT
IF @row_counter = 8 EXEC sp_executesql @sql, @params, @image_type_8 OUTPUT, @image_type_8 OUTPUT, @image_desc_8 OUTPUT, @image_comments_8 OUTPUT
IF @row_counter = 9 EXEC sp_executesql @sql, @params, @image_type_9 OUTPUT, @image_type_9 OUTPUT, @image_desc_9 OUTPUT, @image_comments_9 OUTPUT
IF @row_counter = 10 EXEC sp_executesql @sql, @params, @image_type_10 OUTPUT, @image_type_10 OUTPUT, @image_desc_10 OUTPUT, @image_comments_10 OUTPUT
SET @row_counter = @row_counter + 1
END