Я думаю, вы смущены концепцией дельта.
Либо вы получаете полные нагрузки (весь набор данных), либо только изменения («дельта»).
Если вы имеете дело с полными нагрузками, вы можете сделать усечение + вставку. Таким образом вам не придется иметь дело с новыми или старыми строками или удалениями. Это может быть не представляется возможным из-за ограничений ссылочной целостности и т.д.
Если вы получаете дельту, каждая строка, как правило, положить в 1 из 2 категории:
- Matching ключ =
UPDATE
. Вы можете игнорировать строки с идентичными данными или перезаписывать.
- Нет соответствие ключа =
INSERT
Удаление является особенным. Строки, которые не существуют, не могут быть отправлены вам. Поэтому вам нужно договориться о том, как вы должны справиться с этим. В случае полной загрузки вы можете удалить все локальные строки, которые не существуют в полученном наборе данных.
В случае дельта вы можете согласиться отправить строку с маркером удаления (флаг, дата). Затем вы можете решить, следует ли сохранить строку с маркером удаления (автоматически обрабатывается (1) выше), или если вы должны указать DELETE
свою строку. Я предлагаю сохранить его, потому что рано или поздно кто-то будет обвинять вас в недостатках строк/плохих данных, а затем вы бросаете DELETE_DATE в их лицо.
Для MySQL вы можете использовать INSERT ... ON DUPLICATE KEY UPDATE для реализации функциональности «upsert».
Вам нужно будет предоставить более подробную информацию, если вы хотите получить более конкретную помощь.
Update:
Хорошо, вот пример.Скажите, что у вас есть следующие структуры таблицы:
create table contracts(
contract_id int not null
,details1 varchar(20)
,details2 varchar(20)
,delete_date date
,primary key(contract_id)
);
Всякий раз, когда вы получаете обновленные строки, вставить их во временную таблицу с идентичной структурой:
create table contracts_delta(
contract_id int not null
,details1 varchar(20)
,details2 varchar(20)
,delete_date date
,primary key(contract_id)
);
Некоторые примеры данных:
mysql> select * from contracts;
+-------------+----------+----------+-------------+
| contract_id | details1 | details2 | delete_date |
+-------------+----------+----------+-------------+
| 1 | a1 | a2 | NULL |
| 2 | b1 | b2 | NULL |
| 3 | c1 | c2 | 2011-01-03 |
+-------------+----------+----------+-------------+
mysql> select * from contracts_delta;
+-------------+----------+----------+-------------+
| contract_id | details1 | details2 | delete_date |
+-------------+----------+----------+-------------+
| 2 | b1 | b2 | 2011-01-03 | <-- Row was deleted
| 3 | c1 | c2 | NULL | <-- No longer deleted
| 4 | d1 | d2 | NULL | <-- This is new row
+-------------+----------+----------+-------------+
Используя синтаксис, связанный с предыдущим, вы можете вставить все новые строки. Всякий раз, когда строка уже существует (в двух экземплярах), мы решили обновить столбцы. Обратите внимание, что это обрабатывает удаленные строки автоматически, так как delete_date является регулярным столбцом, как и все остальное.
insert
into contracts(
contract_id
,details1
,details2
,delete_date
)
select contract_id
,details1
,details2
,delete_date
from contracts_delta s
on duplicate key
update contracts.details1 = s.details1
,contracts.details2 = s.details2
,contracts.delete_date = s.delete_date;
После «upsert», данные контракты будут выглядеть следующим образом:
mysql> select * from contracts;
+-------------+----------+----------+-------------+
| contract_id | details1 | details2 | delete_date |
+-------------+----------+----------+-------------+
| 1 | a1 | a2 | NULL |
| 2 | b1 | b2 | 2011-01-03 |
| 3 | c1 | c2 | NULL |
| 4 | d1 | d2 | NULL |
+-------------+----------+----------+-------------+
- На данный момент вы можете удалить таблицу дельта (помните, чтобы воссоздать его в следующем время)
drop table contracts_delta;
- Или вы можете просто усечь его, чтобы сэкономить место. (Вы должны убедиться, что он пуст на следующей загрузке в любом случае)
truncate table contracts_delta;
- Или вы можете сохранить фактическую дельту (переименовать таблицу) упаковывает вам нужны отдельные дельты иногда
alter table contracts_delta rename to contracts_delta_20110115;
спасибо, Ronnis. Я в основном хочу знать, как бороться с дельта-случаем: 1) для строк обновления, mysql кажется не столь точным в отношении того, изменяется ли точная величина или нет. Даже вы обновляете строку с одинаковыми значениями, номер затронутой строки по-прежнему равен 1/2; 2) для удаленных строк, конечно, я не буду удалять строки навсегда. Однако я не уверен, что лучше удалить их в таблицу архивов или просто удалить удаленный флаг в одной таблице. – WilliamLou
@ Ronnis: Я ищу особенно решение для удаления записей. В одном проекте мы используем флаг delete. Но что, если у вас есть уникальное ограничение для столбца, и вы хотите создать новую запись, которая нарушает уникальное ограничение. Определенно было бы лучше удалять данные в этом случае. Но как клиенты получают уведомление об удалении? Я мог представить себе создание второй таблицы для хранения идентификаторов и удаления даты удаленных записей. Решение без дополнительной таблицы было бы лучше. Какие-либо предложения? – Konsumierer