我有两个相同的表位于两个相同的数据库(具有不同的名称)。我想合并这两个表,但它们的主键用于其他表,
这些表看起来像这样:
表A
id column1 column2 column3
___ ________ _______ ________
1 text text text
2 text text text
3 text text text
表B
id column1 column2 column3
___ ________ _______ ________
2 text text text
3 text text text
4 text text text
与表A相关联的表格
链接A
id column1 tableA_ID
___ ________ _______
1 text 2
2 text 3
3 text 4
链接B
id column1 tableA_ID
___ ________ _______
1 text 3
2 text 3
3 text 2
请注意,这些表具有相同的id
,这意味着当我进行合并时,我必须更改第二个表的id
。请记住第二个表的主键在其他表中使用。
我写了这个查询来合并两个表:
INSERT INTO db_A.`Table_A`(`column2`,`column3`)
SELECT `column2`,`column3` FROM db_B.`Table_B`;
此查询将正确地将第二个表的记录复制到第一个表。
现在我想移动与Table B
链接的表的数据,我可以使用相同的查询,但现在外键不匹配,因为它们被链接的ID
已经改变了。
如何更新它们以便ID
再次匹配?
注意:我对这些表没有ON UPDATE CASCADE约束
我希望这是有道理的,我会尝试改进这个问题,以便每个人都理解它。
数据库信息
Type : MySQL
Engine: MyISAM
答案 0 :(得分:3)
我的建议是:
如果您需要更多帮助,请询问。
最好的问候
====================================
更新。更新ID的示例:
UPDATE
Table_A, Link_A
SET
Table_A.id = Table_A.id + 1000,
Link_A.id = Link_A.tableA_ID + 1000,
FROM
Table_A JOIN Link_A
ON
Table_A.id = Link_A.tableA_ID
答案 1 :(得分:2)
如果两个db都相同,我相信你应该将它命名为db_B.Table_A
而不是db_B.Table_B
以避免混淆。但是现在我同意它
--get delta id, use biggest id from db_A and db_B
--to avoid failure because of updating to existing primary key
SELECT @dbBMax := MAX(id) FROM db_B.`Table_B`;
SELECT @dbAMin := MIN(id), @dbAMax := MAX(id) FROM db_A.`Table_A`;
SET @DeltaID := IF(@dbBMax > @dbAMax, @dbBMax, @dbAMax) - @dbAMin + 1;
--drop constraint
ALTER TABLE db_A.`Link_A` DROP FOREIGN KEY `constraint_name_A`;
ALTER TABLE db_A.`Link_B` DROP FOREIGN KEY `constraint_name_B`;
--update ids
UPDATE db_A.`Table_A` SET id = id + @DeltaID;
UPDATE db_A.`Link_A` SET tableA_ID = tableA_ID + @DeltaID;
UPDATE db_A.`Link_B` SET tableA_ID = Link_A.tableA_ID + @DeltaID;
--merge tables
--assume id is auto-increment, don't use auto-increment value,
--so id manually inserted
INSERT INTO db_A.`Table_A`(`id`, `column1`, `column2`,`column3`)
SELECT `id`, `column1`, `column2`,`column3` FROM db_B.`Table_B`;
--assume id is auto-increment, use it, don't insert manually
INSERT INTO db_A.`Link_A`(`column1`, `tableA_ID`)
SELECT `column1`, `tableA_ID` FROM db_B.`Link_A`;
--assume id is auto-increment, use it, don't insert manually
INSERT INTO db_A.`Link_B`(`column1`, `tableA_ID`)
SELECT `column1`, `tableA_ID` FROM db_B.`Link_B`;
如果id
有更多可以修复db_B.Table_B
的数据db_A.Table_A
,此代码可能会在db_B.Table_B
{{1}}添加大跳跃合并表之前/之后很容易..但我认为它是可选的..
答案 2 :(得分:1)
一种简单的方法是将TableB
的{{1}}更新为唯一范围,然后进行合并。如果您的外键已正确设置为级联更改,则数据库将通过此操作保持一致。
您不需要以这种方式对数据库模式进行任何更改,因此没有时间数据不是calid。您还可以确保ID不会发生冲突。查找唯一值的最简单方法是取ID
中ID
的最大值,并将其添加到TableA
中的ID
。
答案 3 :(得分:1)
您可以将ON UPDATE CASCADE
应用于第二个数据库临时与TableB.id
相关的外键的每个表:
ALTER TABLE db2.other_tables_with_fk DROP FOREIGN KEY fk_to_TableB;
ALTER TABLE db2.other_tables_with_fk
ADD CONSTRAINT fk_to_TableB FOREIGN KEY (TableB_id)
REFERENCES TableB(id) ON UPDATE CASCADE;
然后使用Sami's Answer中的技巧,然后删除这样的临时更改:
ALTER TABLE db2.other_tables_with_fk DROP FOREIGN KEY fk_to_TableB;
ALTER TABLE db2.other_tables_with_fk
ADD CONSTRAINT fk_to_TableB FOREIGN KEY (TableB_id)
REFERENCES TableB(id);
然后你的第二个数据库就可以与第一个数据库合并了。
对于 MyISM 或引擎不支持CASCADE
的情况,您可以通过定义Triggers手动模拟它:
CREATE TRIGGER trigger1
AFTER UPDATE
ON TableB
FOR EACH ROW
BEGIN
UPDATE other_tables_with_fk1 SET TableB_id = NEW.id WHERE TableB_id = OLD.id
UPDATE other_tables_with_fk2 SET TableB_id = NEW.id WHERE TableB_id = OLD.id
...
END
即使触发器不可用,您也可以在所有表(包括同时使用外键父表)中,通过某个自定义量(任何大于第一个数据库中使用的最大行ID的数量)增加第二个数据库中的id行数:
UPDATE TableB t SET t.id = (t.id + 10000);
UPDATE related_table_1 t SET t.TableB_id = (t.TableB_id + 10000);
UPDATE related_table_2 t SET t.TableB_id = (t.TableB_id + 10000);
...
然后你可以合并这些数据库。