我甚至不确定怎么说这个问题但是这里有。我需要能够在同一个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
答案 0 :(得分: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
迭代解决方案的另一种方式是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
但请注意,如果有其他非迭代方式执行相同的工作,则应避免使用CURSORS
。但当然有一种情况是你无法避免CURSORs
答案 1 :(得分:5)
以基于集合的方式处理身份的常用方法是通过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;
问题是您无法在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);
,则允许您使用引用内存插入表和输出子句中的源表。是的,你可以输出你需要的所有列:
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;
此方法的问题是SQL Server不允许您插入外键关系的任何一侧,因此如果tableB.NewID引用tableA.ID,则上述操作将失败。要解决此问题,您需要输出到临时表,然后将临时表插入TableB:
{{1}}
<强> Example on SQL Fiddle 强>
答案 2 :(得分:0)
不要使用光标,因为它在性能方面不好。
试试这个链接: http://support2.microsoft.com/kb/111401
您应该使用ROW_NUMBER()并将数据填充到临时表 - 变量表或全局表中。
答案 3 :(得分:0)
如果您只是将数据从一个表插入另一个表,则可以使用以下方法:
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
修改强>
您可以在TableA
的外键myTable
中添加一列。这有助于您在TableA
中获得TableB
的ID。