Очень упрощен, у меня есть две таблицы 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.
Есть несколько решений для этого.
- Используйте цикл while или курсоры для вставки одной строки (RBAR) в Target за раз и используйте
scope_identity()
для заполнения FKTargetChild
. - Добавьте временный столбец в
@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, который используется для указания строк для обновления или удаления.
По какой-то причине они не говорят "строки для вставки, обновления или удаления только" строк "для обновления или удаления".
Любые мысли приветствуются, и совершенно разные решения исходной проблемы очень ценятся.