Очень упрощенно, у меня есть две таблицы Source и Target.
declare @Source table (SourceID int identity(1,2), SourceName varchar(50))
declare @Target table (TargetID int identity(2,2), TargetName varchar(50))
insert into @Source values ('Row 1'), ('Row 2')
Я хотел бы переместить все строки из @Source
в @Target
и узнать TargetID
для каждого SourceID
, потому что существуют также таблицы SourceChild
и TargetChild
, которые также должны быть скопированы, и мне нужно добавить новый TargetID
в TargetChild. TargetID
FK столбец.
Есть несколько решений для этого.
scope_identity()
для заполнения FK в TargetChild
. @Target
и вставьте SourceID
. Затем вы можете присоединиться к этому столбцу, чтобы получить TargetID
для FK в TargetChild
. SET IDENTITY_INSERT OFF
для @Target
и обработайте присвоение новых значений самостоятельно. Вы получите диапазон, который затем используете в TargetChild.TargetID
. Мне не очень нравится ни один из них. Единственный, который я использовал до сих пор, - это курсоры.
Что я действительно хотел бы сделать, так это использовать output
в операторе insert.
insert into @Target(TargetName)
output inserted.TargetID, S.SourceID
select SourceName
from @Source as S
Но это невозможно
The multi-part identifier "S.SourceID" could not be bound.
Но это возможно при слиянии.
merge @Target as T
using @Source as S
on 0=1
when not matched then
insert (TargetName) values (SourceName)
output inserted.TargetID, S.SourceID;
Результат
TargetID SourceID
----------- -----------
2 1
4 3
Я хочу знать, использовали ли вы это? Если у вас есть какие-либо мысли по поводу решения или вы видите какие-либо проблемы с ним? Оно отлично работает в простых сценариях, но, возможно, что-то некрасивое может произойти, когда план запроса становится действительно сложным из-за сложного исходного запроса. Худшим сценарием будет то, что пары TargetID/SourceID на самом деле не совпадают.
MSDN говорит следующее о from_table_name
пункта output.
Это префикс столбца, который определяет таблицу, включенную в предложение FROM оператора DELETE, UPDATE или MERGE, которое используется для указания строк для обновления или удаления.
По какой-то причине они не говорят "строки для вставки, обновления или удаления", только "строки для обновления или удаления".
Любые мысли приветствуются, и совершенно разные решения исходной проблемы будут высоко оценены.