LINUX.ORG.RU

Хранить историю изменений таблицы - другая таблица с ключом актуальной версии [SQL]

 ,


0

1

Я придумал такой паттерн (или антипаттерн?). Наверняка он уже существует. Как он называется? Ну и покритикуйте сам подход.

Когда надо хранить историю изменений в какой-то таблице, т.е. не перезаписывать существующие данные, а добавлять новые, можно сделать так.

схема.png

CREATE TABLE customer_history (
	id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
	customer_id INT NOT NULL,
	date_modified DATETIME NOT NULL,
	name LONGTEXT NOT NULL,
	comment LONGTEXT
);

CREATE TABLE customer (
	customer_id INT PRIMARY KEY NOT NULL,
	customer_history_id INT,
	FOREIGN KEY (customer_history_id) REFERENCES customer_history(id),
	CONSTRAINT ch_id_unique UNIQUE INDEX (customer_history_id)
);

Получить актуальные данные

SELECT ch.customer_id, ch.name, ch.comment
FROM customer c INNER JOIN customer_history ch ON c.customer_history_id=ch.id
Вставить нового клиента
INSERT INTO customer_history (customer_id, date_modified, name, comment)
VALUES (1, SYSDATE(), 'Рога и копыта', 'первая версия');
INSERT INTO customer (customer_id, customer_history_id)
VALUES(1, LAST_INSERT_ID());
Обновить данные о клиенте без перезаписи
INSERT INTO customer_history (customer_id, date_modified, name, comment)
VALUES (1, SYSDATE(), 'Рога и копыта', 'вторая версия');
UPDATE customer
SET customer_history_id=LAST_INSERT_ID()
WHERE customer_id=1;
Посмотреть историю версий
SELECT *
FROM customer_history
WHERE customer_id=1

Linux тут при том, что примеры кода приведены для MySQL.

★★★

Последнее исправление: damix9 (всего исправлений: 3)

Так ли необходима вторая таблица с актуальными данными? Обычно там где нужна история изменений, не так много записей. В итоге не проще ли записывать изменения с таймстампом и просто греп по ид и ордер бай таймстамп?

untitl3d
()
Ответ на: комментарий от untitl3d

В итоге не проще ли записывать изменения с таймстампом и просто греп по ид и ордер бай таймстамп?

Запросы типа «выбери имена 50 последних зарегистрированных пользователей» в таком случае несколько усложняются.

theNamelessOne ★★★★★
()
Ответ на: комментарий от untitl3d

Она не с данными, а с ключами данных. Нет, не проще. Так JOIN с GROUP BY надо. Хороший способ с одной таблицей широко известен, но он другой.

выборка актуальных по дате данных (комментарий)

theNamelessOne,

Актуальные данные хранятся в самой таблице, а старые версии в таблице *_history. Плюсы данной схемы: а) не надо делать join, чтобы получить актуальные данные; б) можно упростить запись новых данных с помощью триггеров: ты просто делаешь update в таблицу customer, как если бы таблицы customer_history не существовало, а запись в таблицу customer_history выполняет триггер автомагически.

Этот способ тоже известен. У него еще плюс: легко массово вставлять одним INSERTом. А минус: нужно иметь вторую таблицу с теми же столбцами - плохо масштабируется, если эта таблица широкая и в нее часто добавляются столбцы, и надо в эту вторую таблицу копировать перед обновлением все данные (если нет триггеров).

У своего способа я такие недостатки пока нашел: чтобы массово вставить, нужно получать IDшники вставленного, и чтобы массово создать новые версии тоже, а это СУБД-специфично и не всегда возможно.

А плюс обоих способов по сравнению с выше упомянутым, что можно JOINить по физическим ключам с последними версиями данных.

damix9 ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.