【问题标题】:mySQL - Copy rows from one database to another with auto increment idsmySQL - 使用自动增量 ID 将行从一个数据库复制到另一个数据库
【发布时间】:2023-03-19 18:35:01
【问题描述】:

注意:抱歉,如果这是重复的,但我找不到解决方案。

我有两个具有完全相同架构的数据库(一个开发数据库和一个实时数据库)。

为了让事情更容易解释,假设我有一个“客户”表和一个“报价”表。两个表都有自动增量 ID,报价表有一个“customerid”列,用作客户表的外键。

我的问题是我的开发数据库中有一些行要复制到实时数据库。当我复制客户行时,我可以轻松获得一个新 ID,但我如何才能将新 ID 分配给“子”报价表行?

我知道我可以手动编写 INSERTS 脚本来解决这个问题,但有更简单的方法吗?

编辑: 这是一个简化的示例,我有大约 15 个表,所有这些表都使用自动增量和外键形成层次结构。实时数据库中的数据要多得多,因此新的 id 会更大(例如 dev.customer.id = 4,live.customer.id = 54)

【问题讨论】:

    标签: mysql


    【解决方案1】:

    无需更改任何 ID 的最简单方法。

    1. 确保您当前位于要复制的记录所在的表中(源数据库)。

    2. 运行以下命令:

    INSERT INTO to_database.to_table 
      SELECT * FROM from_table WHERE some_id = 123;
    

    如果不需要重新映射任何内容,则无需指定列。

    希望有帮助!

    【讨论】:

    • 这对于单个表来说很好,但我有一个带有 FK 约束的表层次结构。正如我所说,我知道它可以手动编写脚本。
    • 值得一提的是,我已经通过创建没有自动增量而是 GUID 的临时表来克服这个问题,然后映射表以提供对每个表中每个记录的“旧”ID 的查找。跨度>
    • 有帮助,但需要更正:当我们运行此查询时,我们需要在 from_database (use from_database) 上,但在查询本身中,它应该显示 from_table from_database.
    • 当您将数据从一个模式复制到另一个模式时,这也适用于一个数据库,即 INSERT INTO schema1.tableName SELECT * FROM schema2.tableName WHERE x=y;
    【解决方案2】:

    我最终设法做到了(根据我的评论),但为了做到这一点,我必须编写一些代码。最后,我创建了一些虚拟表来跟踪旧 id 和新 id 所以。当复制带有 FK 约束的记录时,我只是根据旧的 id 查找新的 id。有点啰嗦,但它奏效了。

    这篇文章现在有点进展,所以我把它标记为答案。如果有人有更好的想法/解决方案,我会很乐意将其“取消标记”为已接受的答案。

    编辑:这里要求的是一些伪代码,我希望能解释我是如何做到的。

    我有两个相关的表如下:

    CREATE TABLE tblCustomers (
      Id int NOT NULL AUTO_INCREMENT,
      Name varchar(50) DEFAULT NULL,
      Address varchar(255) DEFAULT NULL,
      PRIMARY KEY (Id)
    )
    ENGINE = MYISAM
    ROW_FORMAT = fixed;
    
    CREATE TABLE tblQuotes (
      Id int NOT NULL AUTO_INCREMENT,
      CustomerId int(11) DEFAULT NULL,
      QuoteReference varchar(50) DEFAULT NULL,
      PRIMARY KEY (Id)
    )
    ENGINE = MYISAM
    ROW_FORMAT = fixed;
    

    我创建了一个额外的表,用于跟踪旧 ID 和新 ID

    CREATE TABLE tblLookupId (
      Id int NOT NULL AUTO_INCREMENT,
      TableName varchar(50) DEFAULT NULL,
      OldId int DEFAULT NULL,
      NewId int DEFAULT NULL,
      PRIMARY KEY (Id)
    )
    ENGINE = MYISAM
    ROW_FORMAT = fixed;
    

    我的想法是我一次复制一个 tblCustomer 行并在执行过程中跟踪 id,如下所示:

    // copy each customer row from dev to live and track each old and new id
    //
    foreach (customer in tblCustomers)
    {
        // track the old id
        var oldid = customer.id; // e.g. 1
    
        // insert the new record into the target database   
        INSERT newdb.tblCustomers (...) VALUES (...);
    
        // get the new id
        var newid = SELECT LAST_INSERT_ID() // e.g. 245
    
        // insert the old id and the new id in the id lookup table
        INSERT idlookup (TableName, OldId, NewId) VALUES ('tblCustomers', oldid, newid); // this maps 1->245 for tblCustomers
    }
    

    当我使用外键复制表 (tblQuote) 时,我必须首先根据旧的 id 查找新的 id。

    // copy each quote row from dev to live and lookup the foreign key (customer) from the lookup table
    //
    foreach(quote in tblQuotes)
    {
        // get the old foreign key value
        var oldcustomerid = quote.CustomerId; // e.g 1
    
        // lookup the new value
        var newcustomerid = SELECT newid FROM tblIdLookup WHERE TableName='tblCustomers' AND oldid=oldcustomerid; // returns 245
    
        // insert the quote record
        INSERT tblQuotes (CustomerId, ...) VALUES (newcustomerid, ...);
    }
    

    我试图保持简短和重点(并且与语言无关),以便可以看到该技术。在我的真实场景中,我有大约 15 个“级联”表,所以我必须跟踪每个表的新 ID,而不仅仅是 tblCustomer

    【讨论】:

    • 您能否更具体地说明您为解决此问题所做的工作?我知道这已经有一段时间了 - 但这是一个很好的问题,如果有一个完整的答案会很好。
    • @kittykittybangbang 我添加了一些伪代码,希望能解释这种技术。我已经这样做了好几次了,它不快也不漂亮,但它就像一个魅力。
    【解决方案3】:

    使用INSERT ... SELECT

    insert into your_table (c1, c2, ...)
    select c1, c2, ...
    from your_table
    

    其中 c1, c2, ... 是除id 之外的所有列。

    【讨论】:

    • 这适用于第一个表(客户),但第二个(报价)呢?
    • 可能是引用中的嵌套查询,获取正确的客户 ID
    • 谢谢,听起来我们正朝着正确的方向前进。有没有机会举个例子?
    猜你喜欢
    • 2011-04-25
    • 1970-01-01
    • 1970-01-01
    • 2011-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多