【问题标题】:Duplicating records efficiently in tsql在sql中有效地复制记录
【发布时间】:2011-04-12 16:25:50
【问题描述】:

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

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

还有其他有效的方法吗?

【问题讨论】:

    标签: sql tsql performance cursor


    【解决方案1】:

    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 的新值。

    【讨论】:

    • 感谢 Quassnoi,我使用的是 SQL 05。您能否举例说明在 INSERT 中使用 OUTPUT。我想要新添加的记录 ID。
    【解决方案2】:

    您必须一次插入一个表,但如果您允许新父级的子表中的 FK 值与原始父级的 FK 值相同,则可以通过插入集合而不是行来完成.

    假设您有父表的视图,并且在您的 sp 中您将其限制为要从中复制的行(例如,pk=1)。 然后将该行插入到父表中,用 PK=2 代替 PK 值。

    现在使用其中一个子表的第二个视图。在您的 sp 中,将行集限制为 PK=1 的行。同样,将所有这些行插入到同一个子表中,用 PK=2 替换 PK 字段 val。

    【讨论】:

      猜你喜欢
      • 2011-04-08
      • 1970-01-01
      • 1970-01-01
      • 2016-12-28
      • 2018-02-15
      • 1970-01-01
      • 1970-01-01
      • 2015-08-18
      • 1970-01-01
      相关资源
      最近更新 更多