Скопировать строку и зависимые строки в другой таблице и зависимые строки в другой и т. Д. - PullRequest
0 голосов
/ 29 марта 2019

У меня есть таблица со столбцом 'id' и другими различными столбцами. Каждая строка данных будет иметь уникальный идентификатор. Этот идентификатор упоминается в другой таблице, в которой также есть строки с уникальным идентификатором. Каждый из них упоминается в еще одной таблице.

Мы будем называть таблицы «items», «item_options» и «sub_options». Я хочу скопировать одну строку в «items», а также скопировать все, что связано с ее идентификатором в «item_options», и все, что в «sub_options», что связано с идентификаторами в «item_options».

Например:

Скажем, в столбцах "items" есть "id" и "title".
В 'item_options' столбцами являются 'id', 'itemID' и 'option'.
В 'sub_options' столбцами являются 'id', 'item_optionsID' и 'subOption'.

Я могу получить это далеко:

insert into dbo.items (title)
  select title
  from dbo.items where id = '123'

Отсюда я возвращаю новые идентификаторы для вновь скопированных строк в «itmes», затем использую серверный язык для циклического прохождения и копирования «item_options», а затем перебираю их для копирования «sub_options», но я Я очень часто бьюсь по БД, а производительность бьет.

Я хочу сделать все это в SQL, но я не могу понять это.

Для примера данных я попробую это:

dbo.items
id: '123'
title: 'New Car'

dbo.item_options
id: '456'
itemID: '123'
опция: 'Custom Wheels'

id: '457'
itemID: '123'
опция: 'Custom Paint'

dbo.sub_options
id: '789'
item_optionsID: '456'
Подопция: 'Chrome'

id: '790'
item_optionsID: '456'
Подопция: «20 дюймов»

id: '791'
item_optionsID: '457'
Подопция: «Красный»

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

Ответы [ 2 ]

0 голосов
/ 29 марта 2019

ОБНОВЛЕНО (после разъяснений ОП):

Вы пытаетесь вставить новую строку в таблицу items, и вам нужно сохранить новый сгенерированный идентификатор (AKA IDENTITY) для этой строки, чтобы использовать ее в качестве FK в другой операции вставки (в вашем случае вы хотите используйте его в item_options).

если идентификаторы в items и item_options являются идентичностями, то вы можете использовать SCOPE_IDENTITY()

SCOPE_IDENTITY ()

Возвращает последнее значение идентификатора, вставленное в столбец идентификаторов в тот же объем

Узнать больше ...

Итак, ваша вставка будет такой простой:

INSERT INTO dbo.items (title) VALUES ('New Car')

INSERT INTO item_options (itemId, [option]) VALUES (SCOPE_IDENTITY(), 'Custom Wheels')

INSERT INTO sub_options (item_optionsId, subOption) VALUES (SCOPE_IDENTITY(), 'Chrome')

первый SCOPE_IDENTITY() будет принимать последний сгенерированный идентификатор в элементах, а второй - идентификатор item_options и так далее.

вы также можете сохранить идентификатор в переменной для дальнейшего использования, например:

DECLARE 
    @itemId INT 
,   @optionId INT


INSERT INTO dbo.items (title) VALUES ('New Car')

SELECT @itemId = SCOPE_IDENTITY()

INSERT INTO item_options (itemId, [option]) VALUES (@itemId, 'Custom Wheels')

SELECT @optionId = SCOPE_IDENTITY()

INSERT INTO sub_options (item_optionsId, subOption) VALUES (@optionId, 'Chrome')

это даст вам больше гибкости, используя идентификаторы вне его области действия.

Надеюсь, это решит вашу дилемму.

0 голосов
/ 29 марта 2019

Вам нужно захватить новые значения 'id' при вставке в каждую таблицу, чтобы использовать их для ссылок на внешний ключ в дочерних таблицах.Самый надежный способ получения новых идентификаторов - это использование предложения SQL , поскольку оно всегда будет давать правильные идентификаторы и может обрабатывать несколько идентификаторов (многие другие подходы к получению вновь созданного идентификатора записи имеют подводные камни.Стоит избегать).

Вы также хотите заключить его в транзакцию, чтобы обеспечить выполнение операции «все или ничего» (может также потребоваться дополнительная обработка ошибок).

Поскольку предложение output включенооператор insert не допускает значений из исходной таблицы. Я использовал оператор merge для второй части с условием совпадения 1=0, т. е. оно никогда не будет совпадать и поэтому всегда будет вставлено, а merge оператор допускает значения из исходной таблицы в предложении output.

declare @Id int = 123;

declare @ItemOutput table (IdNew int);
declare @ItemOptionOutput table (IdNew int, IdOld int);

begin tran;

insert into dbo.items (title)
  output Inserted.id into @ItemOutput
  select title
  from dbo.items I
  where I.id = @Id;

MERGE INTO dbo.item_options as [Target]
USING (select id, [Option], (select IdNew from @ItemOutput) from dbo.item_options) AS [Source] (id, [Option], IdNew)
ON 1 = 0
WHEN NOT MATCHED THEN
  INSERT (itemID, [Option])
  VALUES ([Source].IdNew, [Source].[Option])
  OUTPUT Inserted.id, [Source].id
  INTO @ItemOptionOutput (IdNew, IdOld);

insert into dbo.sub_options (item_optionsID, subOption)
  select (select O.IdNew from @ItemOptionOutput O where O.IdOld = SO.ID), SubOption
  from dbo.sub_options SO
  where SO.id in (select O.id from dbo.item_options O where O.ItemID = @Id);

commit;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...