Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Массовый INSERT в несколько зависимых таблиц  [new]
Proavtor
Member

Откуда: Москва
Сообщений: 10
Привет!
Задумались с коллегой над решением банальной, казалось бы задачи, и неожиданно поняли, что красивого решения не нашли.
Задача следующая, сформулирую схематично:
Есть таблица, скажем такая:
CREATE TABLE src (id int identity, column_a int, column_b int);

Записей в ней много и полей в реальном случае тоже. Необходимо по запросу из таблицы src экспортировать записи в другую структуру, следующего вида:
CREATE TABLE dst_a (id int identity, column_a int);
CREATE TABLE dst_b (id int identity, column_b int);
CREATE TABLE a2b (id int identity, dst_a_id int, dst_b_id int);

Казалось бы, вполне себе распространенная схема хранения.
Что стало камнем преткновения:
1. Все это работает в многопользовательском режиме.
2. Обрабатывать запросы пользователей пакетами.
Было бы очень удобно, чтобы SQL позволял нам делать, скажем так:
CREATE TABLE #a (src_id int, dst_id int);
CREATE TABLE #b (src_id int, dst_id int);

INSERT INTO dst_a(column_a)
OUTPUT src.id, inserted.id
INTO #a
SELECT column_a FROM src WHERE src.id in (<условие пользователя>);

INSERT INTO dst_b(column_b)
OUTPUT src.id, inserted.id
INTO #b
SELECT column_b FROM src WHERE src.id in (<условие пользователя>);

INSERT INTO a2b(dst_a_id, dst_b_id)
SELECT a.dst_id, b.dst_id FROM #a a JOIN #b b ON a.src_id = b.src_id;

Это было бы красивейшее решение простейшей задачи! Но!.. такое, к сожалению не позволительно, ведь в OUTPUT можно поместить лишь строчки inserted.
Вопрос: можно ли каким-то хитрым хаком сопоставить вставленные identity значения с исходным роусетом?
Какие были варианты, которые очевидно неоптимальны:
1. Вставка по одной записи. - Долго.
2. Вставка identity поле в dst таблицы, используя Serializable Isolation Level. - плохая практика вставки identity и опять таки не исключена возможность взаимоблокировок и длительных ожиданий.
Или может быть, 2-й вариант вполне себе годный? Как бы вы сделали на промышленной системе высокой доступности? Задача кажется банальной, наверняка кто-то уже сталкивался)
И еще вопрос к Oracle спецам, как там обстоят дела с этим?
19 апр 13, 12:28    [14202991]     Ответить | Цитировать Сообщить модератору
 Re: Массовый INSERT в несколько зависимых таблиц  [new]
iap
Member

Откуда: Москва
Сообщений: 47144
Proavtor,

добавить дополнительное техническое поле в две таблицы, и всё развяжется:
CREATE TABLE dst_a (id int identity, column_a int, src_id int not null);
CREATE TABLE dst_b (id int identity, column_b int, src_id int not null);
CREATE TABLE a2b (id int identity, dst_a_id int, dst_b_id int);
19 апр 13, 12:38    [14203109]     Ответить | Цитировать Сообщить модератору
 Re: Массовый INSERT в несколько зависимых таблиц  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Proavtor
к сожалению не позволительно, ведь в OUTPUT можно поместить лишь строчки inserted
Врёте вы всё. Можно любые колонки. Только разве что надо вставлять не через INSERT, а через команду MERGE.
19 апр 13, 12:40    [14203120]     Ответить | Цитировать Сообщить модератору
 Re: Массовый INSERT в несколько зависимых таблиц  [new]
Паганель
Member

Откуда: Винница
Сообщений: 22550
может сиквенсом нагенерить ИДшек?
19 апр 13, 12:40    [14203121]     Ответить | Цитировать Сообщить модератору
 Re: Массовый INSERT в несколько зависимых таблиц  [new]
iap
Member

Откуда: Москва
Сообщений: 47144
iap
Proavtor,

добавить дополнительное техническое поле в две таблицы, и всё развяжется:
CREATE TABLE dst_a (id int identity, column_a int, src_id int not null);
CREATE TABLE dst_b (id int identity, column_b int, src_id int not null);
CREATE TABLE a2b (id int identity, dst_a_id int, dst_b_id int);
И, кстати, почему бы не использовать в качестве ссылки на id источника сами id в dst_a и dst_b?
Тогда и дополнительного поля не надо.
19 апр 13, 12:41    [14203137]     Ответить | Цитировать Сообщить модератору
 Re: Массовый INSERT в несколько зависимых таблиц  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
iap
И, кстати, почему бы не использовать в качестве ссылки на id источника сами id в dst_a и dst_b?
Тогда и дополнительного поля не надо.
Тогда и самих двух полей в самой a2b не надо
19 апр 13, 13:02    [14203307]     Ответить | Цитировать Сообщить модератору
 Re: Массовый INSERT в несколько зависимых таблиц  [new]
iap
Member

Откуда: Москва
Сообщений: 47144
Mnior
iap
И, кстати, почему бы не использовать в качестве ссылки на id источника сами id в dst_a и dst_b?
Тогда и дополнительного поля не надо.
Тогда и самих двух полей в самой a2b не надо
Действительно!
19 апр 13, 13:04    [14203321]     Ответить | Цитировать Сообщить модератору
 Re: Массовый INSERT в несколько зависимых таблиц  [new]
iap
Member

Откуда: Москва
Сообщений: 47144
iap
Mnior
пропущено...
Тогда и самих двух полей в самой a2b не надо
Действительно!
Или, если уж так хочется, можно просто VIEW сделать
19 апр 13, 13:05    [14203331]     Ответить | Цитировать Сообщить модератору
 Re: Массовый INSERT в несколько зависимых таблиц  [new]
Proavtor
Member

Откуда: Москва
Сообщений: 10
Mnior
Proavtor
к сожалению не позволительно, ведь в OUTPUT можно поместить лишь строчки inserted
Врёте вы всё. Можно любые колонки. Только разве что надо вставлять не через INSERT, а через команду MERGE.


Господа, ГЕНИАЛЬНО!!!

MERGE INTO dst_a as target
USING (SELECT id, column_a FROM src) AS source (id, column_a)
ON (source.id is null)
WHEN NOT MATCHED BY TARGET THEN
	INSERT (column_a) VALUES (column_a)
OUTPUT source.id, inserted.id
INTO #a;


Спасибо, Mnior! Век живи, век учись!

А я то думал чем хорош этот самый нововведенный MERGE, так вот оно что! :)

Всем спасибо за участие! День удался! :)
19 апр 13, 13:21    [14203464]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить