РЕДАКТИРОВАТЬ: В моем предыдущем ответе я предположил, что на (id, version)
требуется уникальное ограничение, но на самом деле это не обязательно. Ваше уникальное ограничение только на 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, version = 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
.