类似于T-SQL中变量的数组访问

时间:2009-05-15 17:14:18

标签: tsql

在我的存储过程中,我有多个类似的变量@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

4 个答案:

答案 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中是否有数组。默认情况下没有,虽然谷歌的快速搜索可以指出你的方法,如果你绝对需要它们。