Скопируйте строки таблицы, используя OUTPUT INTO в SQL Server 2005 - PullRequest
1 голос
/ 05 марта 2012

У меня есть таблица, из которой мне нужно копировать записи обратно в себя.В качестве части этого я хочу захватить новые строки с помощью предложения OUTPUT в табличную переменную , чтобы я мог выполнять другие операции со строками в том же процессе.Я хочу, чтобы каждая строка содержала новый ключ и ключ, который был скопирован из .Вот надуманный пример:

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 лает, если число столбцов в INSERT не совпадает с количеством столбцов из инструкции SELECT.Из-за этого я вижу, как это может работать, если я добавлю столбец в MyTable, но это не вариант.Ранее это было реализовано с помощью курсора, который вызывает узкое место в производительности - я намеренно стараюсь этого избежать.

Как мне скопировать эти записи, сохранив ключ скопированной строки таким образом, чтобыдостигнет максимально возможной производительности?

1 Ответ

1 голос
/ 05 марта 2012

Я немного неясен относительно контекста - это в триггере AFTER INSERT.

В любом случае, я не вижу способа сделать это за один вызов.Предложение OUTPUT позволит вам возвращать только те строки, которые вы вставили.Я бы порекомендовал следующее:

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

...

Конечно, вы бы не включили это в триггер AFTER INSERT, потому что он даст вам рекурсивный вызов, но вы можете сделать это в INSTEAD OFВставить триггер.Я могу ошибаться в рекурсивной проблеме;Я всегда избегал рекурсивного вызова, поэтому я никогда не узнавал.Однако использование @@ IDENTITY и ROW_NUMBER () - это трюк, который я использовал несколько раз в прошлом, чтобы сделать нечто подобное.

...