Копировать родительские и дочерние строки в одну таблицу?

У меня есть ситуация, похожая на этот вопрос SO, где я хочу скопировать родительские строки и их дочерние строки из и в ту же таблицу.

Предлагаемый ответ с использованием OUTPUTи MERGEявляется чистым, но рассматривает только одну запись.

Есть ли способ изменить его для обработки нескольких родительских строк?

РЕДАКТИРОВАТЬ

Я попытался изменить инструкцию SQL и придумал это:

DECLARE @fromId int, @toId int;
SET @fromId = 1;
SET @toId = 2;

DECLARE @mapping TABLE (old_id int, new_id int);

INSERT INTO parent_table (col1, col2, col3) 
SELECT @toId, col2, col3
FROM parent_table
WHERE col1 = @fromId;

MERGE child_table tgt
USING (
  SELECT t.parent_id, t.col2, t.col3
  FROM child_table t
  inner join parent_table p on p.id = t.parent_id
  WHERE p.col1 = @toId
) src
ON 0 = 1
WHEN NOT MATCHED THEN
   INSERT (parent_id, col2, col3) VALUES   (src.parent_id, src.col2, src.col3)
OUTPUT src.parent_id, INSERTED.parent_id INTO @mapping (old_id, new_id);

Первая INSERTиз родительских строк работает. Однако вторая вставка вставляет все дочерние строки. Чего мне не хватает?

1 ответ

  1. Вы можете использовать оператора UNION. Мы просто должны сосредоточиться на поддержании номеров столбцов и типов данных :

     select <required-column names, add null if value for a column not required> from parent_table 
        UNION
        select <required-column with null if value for that column not required> from child_table where id in(select id from parent_table);
    

    Например, предположим, что назначение имеет пять столбцов, родитель имеет три столбца, ребенок имеет два столбца.
    Затем, в зависимости от того, куда должны идти родительские идентификаторы, мы могли бы написать :

    insert into destination(col1,col2, col3, col4, col5)
    select col1, null, col2, col3, null from parent_table where key in(<key values>)
    UNION 
    select col1, col2, null, null,null from child_table where key in(<key values>);
    

    Если необходимо скопировать все записи :

    insert into destination(col1,col2, col3, col4, col5)
    select col1, null, col2, col3, null from parent_table
    UNION 
    select col1, col2, null, null,null from child_table where key_column in(select key_column from parent_table);