在我的存储过程中,我有多个类似的变量@V1
,@V2
... @V20
(假设其中有20个)来自记录的FETCHED。我如何使用动态SQL使用这些变量作为参数对另一个存储过程进行20次调用?
当然@V[i]
语法不正确,但它表达了意图
fetch next from maincursor into @status, @V1, @V2, ...
while @i<21
begin
-- ??? execute sp_executesql 'SecondSP', '@myParam int', @myParam=@V[i]
-- or
-- ??? execute SecondSP @V[i]
set @i = @i+1
end
答案 0 :(得分:17)
正如其他人所说,设置一个临时表,将所需的值插入其中。然后“迭代”通过它从这些值执行必要的SQL。这将允许您执行0到MANY值,因此您不必为每个值设置变量。
以下是如何在没有游标的情况下完成此操作的完整示例。
SET NOCOUNT ON
DECLARE @dict TABLE (
id INT IDENTITY(1,1), -- a unique identity column for reference later
value VARCHAR(50), -- your parameter value to be passed into the procedure
executed BIT -- BIT to mark a record as being executed later
)
-- INSERT YOUR VALUES INTO @dict HERE
-- Set executed to 0 (so that the execution process will pick it up later)
-- This may be a SELECT statement into another table in your database to load the values into @dict
INSERT @dict
SELECT 'V1Value', 0 UNION ALL
SELECT 'V2Value', 0
DECLARE @currentid INT
DECLARE @currentvalue VARCHAR(50)
WHILE EXISTS(SELECT * FROM @dict WHERE executed = 0)
BEGIN
-- Get the next record to execute
SELECT
TOP 1 @currentid = id
FROM @dict
WHERE executed = 0
-- Get the parameter value
SELECT @currentvalue = value
FROM @dict
WHERE id = @currentid
-- EXECUTE THE SQL HERE
--sp_executesql 'SecondSP', '@myParam int', @myParam =
PRINT 'SecondSP ' + '@myParam int ' + '@myParam = ' + @currentvalue
-- Mark record as having been executed
UPDATE d
SET executed = 1
FROM @dict d
WHERE id = @currentid
END
答案 1 :(得分:2)
使用#TempTable
如果你在SQL Server 2005,你可以在父存储过程中创建一个#TempTable,它可以在它调用的子存储过程中使用。
CREATE TABLE #TempTable
(col1 datatype
,col2 datatype
,col3 datatype
)
INSERT INTO #TempTable
(col1, col2, col3)
SELECT
col1, col2, col3
FROM ...
EXEC @ReturnCode=YourOtherProcedure
在另一个程序中,您可以访问#TempTable来选择,删除等... 使该子程序一次处理一组数据而不是一个元素
请记住,在SQL中,循环会让性能消失!
答案 2 :(得分:0)
为什么不直接使用表变量,然后循环遍历表获取每个值。
基本上将表中的每一行视为数组单元格,并使用一个包含一列的表。
只是一个想法。 :)
答案 3 :(得分:0)
这似乎是一个奇怪的请求 - 你总是会有一组固定的变量吗?如果数字从20变为21,等等,您是否经常需要声明新的变量呢?
是否有可能不是将值检索到单独的变量中,而是将它们作为单独的行返回,只是在游标中循环它们?
如果没有,您必须按照说明使用各个变量,这是一个解决方案:
declare @V1 nvarchar(100)
set @V1 = 'hi'
declare @V2 nvarchar(100)
set @V2 = 'bye'
declare @V3 nvarchar(100)
set @V3 = 'test3'
declare @V4 nvarchar(100)
set @V4 = 'test4'
declare @V5 nvarchar(100)
set @V5 = 'end'
declare aCursor cursor for
select @V1
union select @V2 union select @V3
union select @V4 union select @V5
open aCursor
declare @V nvarchar(100)
fetch next from aCursor into @V
while @@FETCH_STATUS = 0
begin
exec TestParam @V
fetch next from aCursor into @V
end
close aCursor
deallocate aCursor
我真的不喜欢这个解决方案,看起来很乱,不可扩展。另外,作为旁注 - 你提出问题的方式似乎是在询问T-SQL中是否有数组。默认情况下没有,虽然谷歌的快速搜索可以指出你的方法,如果你绝对需要它们。