Дублирование записей эффективно в TSQL - PullRequest
2 голосов
/ 15 сентября 2010

У меня есть сценарий, где у меня есть родительская таблица, которая имеет отношения «1 ко многим» с двумя или тремя таблицами.Эти дочерние таблицы снова имеют отношения «1 ко многим» с большим количеством таблиц и так далее.Это достигает 5-6 уровней иерархии.

Теперь, основываясь на одном значении первичного ключа родительской таблицы, я хочу продублировать всю информацию, связанную с ней, в базе данных.Я написал хранимую процедуру, которая использует курсоры и вставляет дочерние строки одну за другой и устанавливает новые значения внешнего ключа при каждой вставке.Но это занимает некоторое время, потому что число записей в дочерних таблицах велико.

Есть ли другой эффективный способ сделать это?

Ответы [ 2 ]

2 голосов
/ 15 сентября 2010

В SQL Server 2008:

CREATE TABLE t_parent (id INT NOT NULL PRIMARY KEY IDENTITY, value VARCHAR(100))
CREATE TABLE t_child (id INT NOT NULL PRIMARY KEY IDENTITY, parent INT NOT NULL, value VARCHAR(100))
CREATE TABLE t_grandchild (id INT NOT NULL PRIMARY KEY IDENTITY, child INT NOT NULL, value VARCHAR(100))

INSERT
INTO    t_parent (value)
VALUES  ('Parent 1')

INSERT
INTO    t_parent (value)
VALUES  ('Parent 2')

INSERT
INTO    t_child (parent, value)
VALUES  (1, 'Child 2')

INSERT
INTO    t_child (parent, value)
VALUES  (2, 'Child 2')

INSERT
INTO    t_grandchild (child, value)
VALUES  (1, 'Grandchild 1')

INSERT
INTO    t_grandchild (child, value)
VALUES  (1, 'Grandchild 2')

INSERT
INTO    t_grandchild (child, value)
VALUES  (2, 'Grandchild 3')

DECLARE @tt TABLE (oid INT, nid INT)

MERGE
INTO    t_parent
USING   (
        SELECT  id, value
        FROM    t_parent
        ) p
ON      1 = 0
WHEN NOT MATCHED THEN
INSERT  (value)
VALUES  (value)
OUTPUT  p.id, INSERTED.id
INTO    @tt;

MERGE
INTO    t_child
USING   (
        SELECT  c.id, p.nid, c.value
        FROM    @tt p
        JOIN    t_child c
        ON      c.parent = p.oid
        ) c
ON      1 = 0
WHEN NOT MATCHED THEN
INSERT  (parent, value)
VALUES  (nid, value)
OUTPUT  c.id, INSERTED.id
INTO    @tt;

INSERT
INTO    t_grandchild (child, value)
SELECT  c.nid, gc.value
FROM    @tt c
JOIN    t_grandchild gc
ON      gc.child = c.oid

В более ранних версиях SQL Server вам нужно будет сделать SELECT, а затем INSERT, чтобы узнать новые значения PRIMARY KEY.

1 голос
/ 15 сентября 2010

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

Скажем, у вас есть представление о родительской таблице, и в вашем sp вы ограничиваете ее строкой для копирования (скажем, pk = 1).Затем вставьте эту строку в родительскую таблицу, заменив PK = 2 для значения PK.

Теперь используйте второе представление одной из дочерних таблиц.В вашем sp, ограничьте набор строк теми, у которых PK = 1.Снова вставьте все эти строки в ту же дочернюю таблицу, подставив PK = 2 для поля PK val.

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