我正在尝试合并(联合)具有相同结构的两个表。在已知的行块中,主键(auto_increment整数)在两个表中用于不同的数据。让我们说它是主键2000-2150的行。将表B中的这些记录重新编号为未使用的值(例如,在3000以上的范围内)的最佳方法是什么,以便合并可以在没有冲突的情况下进行?我应该在适当的位置更新它们(例如,通过在该范围内为每个ID添加1000),还是有更好的方法?
注意:
此表的所有引用都声明为ON UPDATE CASCADE
,因此我可以安全地对它们重新编号而不会产生任何后果。
我可以处理合并的其余部分。两个表都包含有用的数据,当重复该范围之外的密钥时,我将保留表A中的版本。
答案 0 :(得分:0)
将数字更改为数字的负数将起作用。现在或将来都不会发生碰撞。
答案 1 :(得分:0)
从评论转到答案。
如果可以的话,请提供您正在尝试的查询,以便我们可以解决一些问题。但作为一个简短的答案...
在您选择的表B中,您可以:
select Id, col2, col3, col4
from TableA
union all
select Id + 3000, col2, col3, col4
from TableB;
也就是说,如果Id列是数字。
有一点需要注意,如果您打算尝试将这些记录插入Table A
,则需要禁用自动排序。
另一种选择,如果您要将记录从Table A
插入Table B
,将Table B
中孤立子记录的可能问题放在一边,则可以省略{{1} Id
上的Table B
列,与插入时一样,将使用自动增量ID生成新的SELECT INTO TableA...
值。
对于孤儿子记录问题,您还可以向名为Id
的{{1}}添加一个新列,该列将包含来自TableA
的{{1}}原始TableBId
仍然可以访问与Id
相关联的旧数据。另一种选择是针对同一想法的新子表。这样可以防止您改变TableB
结构,但仍然提供一些方法来保留对旧数据的访问权。
如果你有更多关于你最想做什么的信息,我们可能会提出一个更好的解决方案,但这应该让你开始。
答案 2 :(得分:0)
识别"重复"
的ID值 SELECT b.id
FROM b
JOIN a
ON b.id = a.id
识别新的" id"值
SELECT MAX(m.id)
FROM ( SELECT MAX(ma.id) AS id
FROM a ma
UNION ALL
SELECT MAX(mb.id) AS id
FROM b mb
) m
生成新的"未使用的" id值
SELECT s.id AS old_id
, @id := @id + 1 AS new_id
FROM ( SELECT b.id
FROM b
JOIN a
ON b.id = a.id
ORDER BY b.id
) s
CROSS
JOIN ( SELECT @id := MAX(ma.id) FROM a ma) i
ORDER
BY s.id
执行更新
UPDATE b t
JOIN ( SELECT r.*
FROM ( SELECT s.id AS old_id
, @id := @id + 1 AS new_id
FROM ( SELECT b.id
FROM b
JOIN a
ON b.id = a.id
ORDER BY b.id
) s
CROSS
JOIN ( SELECT @id = MAX(m.id)
FROM ( SELECT MAX(ma.id) AS id
FROM a ma
UNION ALL
SELECT MAX(mb.id) AS id
FROM b mb
) m
) i
ORDER
BY s.id
) r
) q
ON t.id = q.old_id
SET t.id = q.new_id
答案 3 :(得分:0)
如果你经常这样做,尝试一些像其他人描述的花哨的方式,如果它是一个完成一个计时器的事情,只需这样做,并确保你不打破任何东西:
修复b中的条目(如果级联有效)
更新b set b.id = b.id + offset其中b.id in(从a中选择id)
这只是"移动"复制到新位置,还要确保没有人会在非重复范围内从备份中恢复已删除的数据。
另一种方法是按记录记录并将数据插入表a,然后使用mysqllastinsertid更新指向旧值的所有条目。