在sql中有效地复制记录

时间:2010-09-15 13:07:58

标签: sql tsql performance cursor

我有一个场景,我有一个父表,它与两个或三个表有“1对多”的关系。这些子表再次与更多表有“1对多”关系,依此类推。这最多可达5到6个层次结构。

现在,基于父表的单个主键值,我想在数据库中复制与其相关的所有信息。我编写了一个存储过程,它使用游标并逐个插入子行,并为每个插入设置新的外键值。但由于子表中的记录数量很高,因此耗费了一些时间。

还有其他有效的方法吗?

2 个答案:

答案 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。