1

我正在将一个相当大的数据库迁移到一个新的数据库设计。现有结构具有多个表,用于表示不同商店的相同数据。

例如:

`store1_tickets`
--------------------
| id    | customer |
--------------------
|     1 |       29 |
--------------------

`store2_tickets`
--------------------
| id    | customer |
--------------------
|     1 |       54 |
--------------------

我现在正在合并到这样的表中:

`tickets`
----------------------------------------
| id    | legacy_id | store | customer |
----------------------------------------
|     1 |         1 |     1 |       29 |
|     2 |         1 |     2 |       54 |
----------------------------------------

这种模式对几个组件(客户、供应商、约会......)重复。

我正在制作一个(PHP)脚本来对 INSERT 语句执行 ETL。在转换数据时,它必须保持新工单 ID 的总和。在 INSERT 语句之后,我正在创建一个 UPDATE 语句来更改其他表中的相应 ID(例如,一旦我重新编号表,就更改表customer中的字段。ticketscustomers

我害怕运行更新(在所有插入之后)并让它进行一种级联,将customer1 更改为 54,然后当它达到customer54 时,将其更改为 243,依此类推。

如何正确修复 ID?票证表是唯一保留旧 ID 的表格,因为我实际上会将其用作多列 auto_increment(每个商店都必须有自己的递增票证 ID 用于显示目的)。复杂性在于有如此多的表相互引用,因此在脚本中直接更新任何 ID 都变得非常复杂。

有没有更好的方法来解决这个问题,或者有什么方法可以防止更新级联?我几乎认为从id一个非常高的数字开始(由于记录数必须至少为 100k),然后在一切都说完之后,我可以将所有 ID 减少该值。

4

1 回答 1

0

我决定采用我提出的“从高 ID 开始”的方法。

我的脚本是这样的(从真实代码超级简化)。

<?php
    /* Temp ID to add to each legacy ID
       This MUST be MUCH GREATER than any record counts combined can possibly reach
       In my case, all rows in my existing 7 tables (per data type)
       totalled about ~350,000, so I rounded up generously to be safe
    */
    define('TEMP_ID', 400000);

    // Whole process repeated for each store, and numerous types of data
    $query = $db->query('SELECT * FROM store1_tickets');

    // Insert statement
    $insert_sql = 'INSERT INTO tickets SET id = %1$d, legacy_id = %2$d,
        store = 1, customer = %3$d;';

    // Update for other tables linked to this ID
    $update_sql = 'UPDATE logs SET ticket = %1$d WHERE ticket = %2$d;'."\n";
    $update_sql.= 'UPDATE appointments SET ticket = %1$d WHERE ticket = %2$d;';

    // Counter (kept for going between sessions for large datasets)
    $ticket_id = 0;

    while($row = $db->fetch_row($query)){

        /* Insert with temp IDs for references to legacy data
           Note how the legacy id itself is stored un-touched, we are
           just worried about links to other tables
        */
        $sql .= sprintf($insert_sql, ++$ticket_id, $row['id'],
            $row['customer'] + TEMP_ID);

        /* Now I store an update for the tables linked to this ticket
           to update to the new ID from the old (with temp added)
        */
        $patch .= sprintf($update_sql, $ticket_id, $row['id'] + TEMP_ID);

     }

?>

然后我运行所有内容$sql以输入原始数据,然后运行$patch语句来修复所有链接。

现在,一旦我运行了所有这些查询(存储在 .sql 文件中并使用批处理脚本转储),我会运行一些整体“清理”查询以在需要的地方减少 ID。

UPDATE logs SET ticket = ticket - 400000 WHERE ticket > 400000;
UPDATE appointments SET ticket = ticket - 400000 WHERE ticket > 400000;
UPDATE tickets SET customer = customer - 400000 WHERE customer > 400000;

这对我来说非常好用,来自数百个表的超过 100MB 的 MySQL 数据。运行实际查询花费了相当多的时间(我推荐很棒的脚本BigDump),但到目前为止似乎一切都很好。

于 2013-10-17T15:10:52.783 回答