简体   繁体   English

在SQL Server 2005中使用OUTPUT INTO复制表行

[英]Copy table rows using OUTPUT INTO in SQL Server 2005

I have a table which I need to copy records from back into itself. 我有一个表,我需要将记录从表复制回自身。 As part of that, I want to capture the new rows using an OUTPUT clause into a table variable so I can perform other opertions on the rows as well in the same process. 作为其中的一部分,我想使用OUTPUT子句将新行捕获到表变量中,以便我可以在同一过程中对行执行其他操作。 I want each row to contain its new key and the key it was copied from . 我希望每一行都包含其新密钥和从中复制的密钥 Here's a contrived example: 这是一个人为的示例:

INSERT 
    MyTable (myText1, myText2) -- myId is an IDENTITY column
OUTPUT  
    Inserted.myId, 
    Inserted.myText1, 
    Inserted.myText2 
INTO
    -- How do I get previousId into this table variable AND the newly inserted ID? 
    @MyTable    
SELECT 
    -- MyTable.myId AS previousId,
    MyTable.myText1,
    MyTable.myText2
FROM
    MyTable
WHERE
    ...

SQL Server barks if the number of columns on the INSERT doesn't match the number of columns from the SELECT statement. 如果INSERT上的列数与SELECT语句中的列数不匹配,则SQL Server会发出吠声。 Because of that, I can see how this might work if I added a column to MyTable, but that isn't an option. 因此,如果将列添加到MyTable中,我可以看到它如何工作,但这不是一个选择。 Previously, this was implemented with a cursor which is causing a performance bottleneck -- I'm purposely trying to avoid that. 以前,这是通过游标实现的,这会导致性能瓶颈-我有意避免这种情况。

How do I copy these records while preserving the copied row's key in a way that will achieve the highest possible performance? 如何在保留复制行的键的同时复制这些记录,以实现最高的性能?

I'm a little unclear as to the context - is this in an AFTER INSERT trigger. 我不清楚上下文-这是在AFTER INSERT触发器中。

Anyway, I can't see any way to do this in a single call. 无论如何,我看不出有任何方法可以在一个电话中做到这一点。 The OUTPUT clause will only allow you to return rows that you have inserted. OUTPUT子句仅允许您返回已插入的行。 What I would recommend is as follows: 我建议如下:

DECLARE @MyTable (
    myID INT, 
    previousID INT, 
    myText1 VARCHAR(20), 
    myText2 VARCHAR(20)
)

INSERT @MyTable (previousID, myText1, myText2) 
SELECT myID, myText1, myText2 FROM inserted

INSERT MyTable (myText1, myText2) 
SELECT myText1, myText2 FROM inserted

-- @@IDENTITY now points to the last identity value inserted, so...
UPDATE m SET myID = i.newID
FROM @myTable m, (SELECT @@IDENTITY - ROW_NUMBER() OVER(ORDER BY myID DESC) + 1 AS newID, myID FROM inserted) i
WHERE m.previousID = i.myID

...

Of course, you wouldn't put this into an AFTER INSERT trigger, because it will give you a recursive call, but you could do it in an INSTEAD OF INSERT trigger. 当然,您不会将其放入AFTER INSERT触发器中,因为它将给您递归调用,但是您可以在INSTEAD OF INSERT触发器中进行。 I may be wrong on the recursive issue; 我可能在递归问题上错了; I've always avoid the recursive call, so I've never actually found out. 我总是避免递归调用,所以我从来没有真正发现过。 Using @@IDENTITY and ROW_NUMBER(), however, is a trick I've used several times in the past to do something similar. 但是,使用@@ IDENTITY和ROW_NUMBER()是我过去几次使用过的技巧来做类似的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM