我有一个场景,我有一个父表,它与两个或三个表有“1对多”的关系。这些子表再次与更多表有“1对多”关系,依此类推。这最多可达5到6个层次结构。
现在,基于父表的单个主键值,我想在数据库中复制与其相关的所有信息。我编写了一个存储过程,它使用游标并逐个插入子行,并为每个插入设置新的外键值。但由于子表中的记录数量很高,因此耗费了一些时间。
还有其他有效的方法吗?
答案 0 :(得分:2)
在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 :(得分:1)
您必须一次插入一个表,但如果允许新父表的子表中的FK值与原始父表的FK值相同,则可以通过插入集而不是行来执行此操作
假设您有父表的视图,并且在sp中将其限制为要复制的行(pk = 1,比如说)。 然后将该行插入父表中,用PK = 2代替PK val。
现在使用其中一个子表的第二个视图。在sp中,将行集限制为PK = 1的行。再次,将所有这些行插入到相同的子表中,用PK = 2替换PK字段val。