代码之家  ›  专栏  ›  技术社区  ›  tsilb

TSQL:使用“插入”更新到“选择自”

  •  11
  • tsilb  · 技术社区  · 17 年前

    目前,我一直在使用我编写的工具,手动检索旧记录,将其插入新数据库,并更新旧数据库中的v2id字段,以显示其在新数据库中的相应ID位置。

    例如,我从MV5.Posts中选择并插入到MV6.Posts中。插入后,我在MV6.Posts中检索新行的ID,并在旧的MV5.Posts.MV6ID字段中更新它。

    有没有一种方法可以通过插入选择来进行更新,这样我就不必手动处理每条记录?我正在使用SQLServer2005开发版。

    7 回复  |  直到 12 年前
        1
  •  10
  •   binki    13 年前

    迁移的关键是要做几件事: 首先,在没有当前备份的情况下,不要做任何事情。 第二,如果密钥将要更改,则至少需要临时将新旧密钥存储在新结构中(如果密钥字段向用户公开,则为永久性存储,因为用户可能会通过它进行搜索以获取旧记录)。

    接下来,您需要彻底了解与子表的关系。如果更改键字段,则所有相关表也必须更改。这就是存储新旧钥匙的方便之处。如果您忘记更改其中任何一个,数据将不再正确,并且将毫无用处。所以这是关键的一步。

    挑选一些特别复杂数据的测试用例,确保为每个相关表包含一个或多个测试用例。将现有值存储在工作表中。

    要开始迁移,请使用“从旧表中选择”命令插入到新表中。根据记录的数量,您可能希望通过批量循环(一次不能循环一条记录)来提高性能。如果新密钥是一个标识,只需将旧密钥的值放入其字段中,并让数据库创建新密钥。

    然后对相关表执行相同的操作。然后使用表中的旧键值更新外键字段,如下所示:

    Update t2
    set fkfield = newkey
    from table2 t2
    join table1 t1 on t1.oldkey = t2.fkfield
    

    通过运行测试用例并将数据与迁移前存储的数据进行比较来测试迁移。彻底测试迁移数据至关重要,否则您无法确保数据与旧结构一致。移徙是一项非常复杂的行动;花点时间,有条不紊、彻底地去做是值得的。

        2
  •  5
  •   Joel    17 年前

    最简单的方法可能是在MV6.Posts上为oldId添加一列,然后将旧表中的所有记录插入到新表中。最后,使用以下内容更新新表中与oldId匹配的旧表:

    UPDATE mv5.posts
    SET newid = n.id
    FROM mv5.posts o, mv6.posts n 
    WHERE o.id = n.oldid
    

        3
  •  3
  •   JoshBerke    17 年前

    我知道你能做的最好的就是 output clause . 假设您有SQL2005或2008。

    USE AdventureWorks;
    GO
    DECLARE @MyTableVar table( ScrapReasonID smallint,
                               Name varchar(50),
                               ModifiedDate datetime);
    INSERT Production.ScrapReason
        OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate
            INTO @MyTableVar
    VALUES (N'Operator error', GETDATE());
    

    它仍然需要第二次传递来更新原始表;然而,它可能会帮助您简化逻辑。是否需要更新源表?您可以将新id存储在第三个交叉引用表中。

        4
  •  2
  •   tpdi    17 年前

    呵呵。我记得在迁移中这样做过。

    insert into newtable select ... from oldtable ,--以及后续记录的“缝合”更容易。在“stitch”中,您可以在insert中更新子表的外键,方法是对新的父表执行子选择( insert into newchild select ... (select id from new_parent where old_id = oldchild.fk) as fk, ... from oldchild )或者您将插入子项并执行单独的更新以修复外键。

    在一次插入中执行此操作速度更快;在单独的步骤中执行这一操作意味着您的插入不依赖于顺序,并且可以在必要时重新执行。

    old_id 列,或者,如果旧系统公开了id,因此用户将密钥用作数据,则可以保留它们以允许基于旧id进行使用查找。

    实际上,如果外键定义正确,可以使用systables/information模式生成insert语句。

        5
  •  2
  •   dance2die    17 年前

    有没有一种方法可以通过插入选择来进行更新,这样我就不必手动处理每条记录?

    人工 但是 自动地 ,在上创建触发器 MV6.Posts 因此 UPDATE MV5.Posts 在插入时自动执行 MV6.员额 .

    你的扳机可能看起来像,

    create trigger trg_MV6Posts
    on MV6.Posts
    after insert
    as
    begin
        set identity_insert MV5.Posts on
    
        update  MV5.Posts
        set ID = I.ID
        from    inserted I
    
        set identity_insert MV5.Posts off
    end
    
        6
  •  1
  •   Brann    17 年前

    另外,不能用一条sql语句更新两个不同的表

    但是,您可以使用触发器来实现您想要做的事情。

        7
  •  1
  •   Christian Johansson    17 年前

    在MV6.Post.OldMV5Id中创建一列

    选择来自MV5.Post

    然后更新MV5.Post.MV6ID