我正在向新的数据库设计进行相当大的数据库迁移。现有结构具有多个表,用于表示不同存储的相同数据。
例如:
`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(,但到目前为止,它似乎一切看起来都不错。