编辑:在我之前的回答中,我建议在 上需要一个唯一约束(id, version)
,但实际上这不是必需的。您对 only 的唯一约束id
足以使解决方案发挥作用。
您应该能够REPLACE
按如下方式使用该命令:
REPLACE INTO main
SELECT IFNULL(m.id, s.id) id,
IFNULL(m.version, s.version) version,
IFNULL(m.data, s.data) data
FROM secondary s
LEFT JOIN main m ON (m.id = s.id AND m.version > s.version);
测试用例:
CREATE TABLE main (
id int,
version int,
data varchar(50),
PRIMARY KEY (id)
);
CREATE TABLE secondary (id int, version int, data varchar(50));
INSERT INTO main VALUES (1, 3, 'first data set');
INSERT INTO main VALUES (2, 2, 'second data set');
INSERT INTO main VALUES (3, 5, 'third data set');
INSERT INTO secondary VALUES (1, 4, 'updated 1st');
INSERT INTO secondary VALUES (3, 3, 'udated 2nd');
INSERT INTO secondary VALUES (4, 1, 'new 4th');
结果:
SELECT * FROM main;
+----+---------+-----------------+
| id | version | data |
+----+---------+-----------------+
| 1 | 4 | updated 1st |
| 2 | 2 | second data set |
| 3 | 5 | third data set |
| 4 | 1 | new 4th |
+----+---------+-----------------+
4 rows in set (0.00 sec)
作为旁注,为了帮助您了解该REPLACE
命令中发生的情况,请注意以下几点:
SELECT s.id s_id, s.version s_version, s.data s_data,
m.id m_id, m.version m_version, m.data m_data
FROM secondary s
LEFT JOIN main m ON (m.id = s.id AND m.version > s.version);
+------+-----------+-------------+------+-----------+----------------+
| s_id | s_version | s_data | m_id | m_version | m_data |
+------+-----------+-------------+------+-----------+----------------+
| 1 | 4 | updated 1st | NULL | NULL | NULL |
| 3 | 3 | udated 2nd | 3 | 5 | third data set |
| 4 | 1 | new 4th | NULL | NULL | NULL |
+------+-----------+-------------+------+-----------+----------------+
3 rows in set (0.00 sec)
然后,IFNULL()
如果存在主表中的最新版本,则函数负责“覆盖”主表中的最新版本,如 id=3,版本=5 的情况。因此如下:
SELECT IFNULL(m.id, s.id) id,
IFNULL(m.version, s.version) version,
IFNULL(m.data, s.data) data
FROM secondary s
LEFT JOIN main m ON (m.id = s.id AND m.version > s.version);
+------+---------+----------------+
| id | version | data |
+------+---------+----------------+
| 1 | 4 | updated 1st |
| 3 | 5 | third data set |
| 4 | 1 | new 4th |
+------+---------+----------------+
3 rows in set (0.00 sec)
上面的结果集仅包含来自辅助表的记录,但如果这些记录中的任何一条恰好在主表中有更新版本,则该行将被主表中的数据覆盖。这是我们提供REPLACE
命令的输入。