循环遍历SQL中的SELECT结果集

Rev*_*les 7 sql t-sql sql-server sql-server-2008

我甚至不确定如何说出这个问题但是这里有.我需要能够在同一个SQL脚本中循环遍历结果集,并在更多SQL中使用结果.

例如

begin
SELECT (SELECT ColumnA, ColumnB from SomeTable) as x

loop through x(
    INSERT ColumnA into TableA
    INSERT ColumnB into TableB
    )
end
Run Code Online (Sandbox Code Playgroud)

但我忘了这样做的确切方法.我知道我之前在以前的位置上已经完成了,但我找不到该公司文件中的代码.

显然,这是一个非常粗略和基本的例子,我计划用结果集做更多的事情,但我只是以此为例.


编辑:这是一个更接近我想要做的事情的例子,如果这将有所帮助.

begin
    while(select columnA, columnB, columnC, columnD from myTable) as x

    begin
        INSERT columnA, columnB into TableA

        (get newly created ID of TableA - but that's a separate question involving @@IDENTITY)

        INSERT NewID, columnC, columnD into TableB
    end loop
end
Run Code Online (Sandbox Code Playgroud)

Gio*_*uri 15

SQL它被称为CURSORS.基本结构CURSOR是:

 DECLARE @ColumnA INT, @ColumnB INT

 DECLARE CurName CURSOR FAST_FORWARD READ_ONLY
 FOR
    SELECT  ColumnA, ColumnB
    FROM    SomeTable

 OPEN CurName

 FETCH NEXT FROM CurName INTO @ColumnA, @ColumnB

 WHILE @@FETCH_STATUS = 0
    BEGIN

        INSERT  INTO TableA( ColumnA )
        VALUES  ( @ColumnA )
        INSERT  INTO TableB( ColumnB )
        VALUES  ( @ColumnB )

        FETCH NEXT FROM CurName INTO @ColumnA, @ColumnB

    END

 CLOSE CurName
 DEALLOCATE CurName
Run Code Online (Sandbox Code Playgroud)

迭代解决方案的另一种方式是WHILE循环.但要使其工作,您应该在表中具有唯一的标识列.例如

DECLARE @id INT

SELECT TOP 1 @id  =  id FROM dbo.Orders ORDER BY ID

WHILE @id IS NOT NULL
BEGIN

  PRINT @id

  SELECT TOP 1 @id  =  id FROM dbo.Orders WHERE ID > @id ORDER BY ID
  IF @@ROWCOUNT = 0
  BREAK

END
Run Code Online (Sandbox Code Playgroud)

但请注意,CURSORS如果有替代方法而不是迭代方式执行相同的工作,则应该避免使用.但当然有一种情况是你无法避免的CURSORs


Gar*_*thD 5

处理以基于集合的方式获取身份的常用方法是通过以下OUTPUT条款:

INSERT INTO TableA (ColumnA, ColumnB)
OUTPUT inserted.Id, inserted.ColumnA, inserted.ColumnB
SELECT  ColumnA, ColumnB
FROM    MyTable;
Run Code Online (Sandbox Code Playgroud)

这里的问题是你理想的做法是:

INSERT INTO TableA (ColumnA, ColumnB)
OUTPUT inserted.Id, MyTable.ColumnC, inserted.ColumnD 
    INTO TableB (AID, ColumnC, ColumnD)
SELECT  ColumnA, ColumnB
FROM    MyTable;
Run Code Online (Sandbox Code Playgroud)

问题是您无法在OUTPUT中引用源表,只能引用目标.幸运的是有一个解决方法MERGE,因为这允许你使用引用驻留内存插入表和输出子句中的源表,如果你使用MERGE永远不会是真的条件你可以输出所有列你需要:

WITH x AS
(   SELECT  ColumnA, ColumnB, ColumnC, ColumnD
    FROM    MyTable
)
MERGE INTO TableA AS a
USING x
    ON 1 = 0 -- USE A CLAUSE THAT WILL NEVER BE TRUE
WHEN NOT MATCHED THEN 
    INSERT (ColumnA, ColumnB)
    VALUES (x.ColumnA, x.ColumnB)
OUTPUT inserted.ID, x.ColumnC, x.ColumnD INTO TableB (NewID, ColumnC, ColumnD);
Run Code Online (Sandbox Code Playgroud)

此方法的问题是SQL Server不允许您插入外键关系的任何一侧,因此如果tableB.NewID引用tableA.ID,则上述操作将失败.要解决此问题,您需要输出到临时表,然后将临时表插入TableB:

CREATE TABLE #Temp (AID INT, ColumnC INT, ColumnD INT);
WITH x AS
(   SELECT  ColumnA, ColumnB, ColumnC, ColumnD
    FROM    MyTable
)
MERGE INTO TableA AS a
USING x
    ON 1 = 0 -- USE A CLAUSE THAT WILL NEVER BE TRUE
WHEN NOT MATCHED THEN 
    INSERT (ColumnA, ColumnB)
    VALUES (x.ColumnA, x.ColumnB)
OUTPUT inserted.ID, x.ColumnC, x.ColumnD INTO #Temp (AID, ColumnC, ColumnD);

INSERT TableB (AID, ColumnC, ColumnD)
SELECT AID, ColumnC, ColumnD
FROM #Temp;
Run Code Online (Sandbox Code Playgroud)

关于SQL小提琴的例子