在 SQL 中遍历 SELECT 个结果集

Looping through SELECT result set in SQL

我什至不确定如何表达这个问题,但就这样吧。我需要能够在同一个 SQL 脚本中遍历结果集,并在更多 SQL.

中使用结果

例如

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

loop through x(
    INSERT ColumnA into TableA
    INSERT ColumnB into TableB
    )
end

但是我忘记了具体的做法。我知道我以前在以前的职位上做过,但我无法在我那家公司的文件中找到它的代码。

显然,这是一个非常粗糙和基本的示例,我计划对结果集做更多的事情,但我只是举个例子。


编辑:这是我想要做的更详细的示例,以防这会有所帮助。

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

不要使用游标,因为它对性能不利。

试试这个 link: http://support2.microsoft.com/kb/111401

您应该使用 ROW_NUMBER() 并将数据填充到临时数组 table - 变量或全局 table。

如果您只是将数据从一个 table 插入到另一个,您可以使用这种方法:

insert into TableA (ColumnA, ColumnB, myTableID)
select (ColumnA, ColumnB, myTableID) from myTable

insert into TableB (ColumnC, ColumnD, myTableID)
select m.ColumnC, m.ColumnD, a.TableAid
from myTable m
join TableA a
    on m.myTableID = a.myTableID

编辑:

您可以在myTable外键的TableA中添加一列。这将帮助您在 TableB.

中获取 TableA 的 ID

SQL中称为CURSORSCURSOR的基本结构是:

 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

另一种迭代求解的方法是WHILE循环。但要使其正常工作,您应该在 table 中具有唯一标识列。例如

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

但是请注意,如果有替代方法而不是迭代方法来完成相同的工作,您应该避免使用 CURSORS。但是当然有些情况是你无法避免的CURSORs

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

INSERT INTO TableA (ColumnA, ColumnB)
OUTPUT inserted.Id, inserted.ColumnA, inserted.ColumnB
SELECT  ColumnA, ColumnB
FROM    MyTable;

这里的问题是您最理想的做法是:

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

问题是您不能在输出中引用源 table,只能引用目标。幸运的是,使用 MERGE 可以解决此问题,因为这允许您在使用 [=15] 时同时引用插入的常驻内存 table 和输出子句中的源 table =] 在永远不会成立的条件下,您可以输出所需的所有列:

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);

此方法的问题是 SQL 服务器不允许您插入外键关系的任何一侧,因此如果 tableB.NewID 引用 tableA.ID 则上述操作将失败.要解决此问题,您需要输出到临时 table,然后将临时 table 插入 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;

Example on SQL Fiddle