MySQL ID Rolling


MySQL ID Rolling

我正在向新的数据库设计进行相当大的数据库迁移。现有结构具有多个表,用于表示不同存储的相同数据。

例如:

`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(例如,在对customers表重新编号后更改tickets表中的customer字段。

我害怕运行 UPDATE(在所有 INSERT 之后(并让它做一种级联,它customer 1 更改为 54,然后当它达到 customer 54 时,将其更改为 243,依此类推。

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

有没有更好的方法,或者某种防止更新级联的方法?我几乎认为像从一个非常高的数字开始id(由于记录计数,必须至少为 100k(,然后在一切都说完并完成之后,我可以将所有 ID 递减该值。

我决定采用我提出的"从高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(,但到目前为止,它似乎一切看起来都不错。