Поки @WW. відповідь є гарною відповіддю. Ще один спосіб - зробити стовпець версій і зберегти всі ваші версії в одній таблиці.
Для одного столу ви підходите :
- Використовуйте прапор для позначення останнього ala Word Press
- АБО робити неприємно більше, ніж версія
outer join
.
Приклад SQL outer join
методу, що використовує ревізійні номери:
SELECT tc.*
FROM text_content tc
LEFT OUTER JOIN text_content mc ON tc.path = mc.path
AND mc.revision > tc.revision
WHERE mc.revision is NULL
AND tc.path = '/stuff' -- path in this case is our natural id.
Погана новина - вищезазначене вимагає, outer join
і зовнішні з'єднання можуть бути повільними. Хороша новина полягає в тому, що створення нових записів теоретично дешевше, тому що ви можете це зробити за одну операцію запису з поза транзакціями (якщо припустити, що ваша база даних є атомною).
Прикладом нової редакції для '/stuff'
може бути:
INSERT INTO text_content (id, path, data, revision, revision_comment, enabled, create_time, update_time)
(
SELECT
(md5(random()::text)) -- {id}
, tc.path
, 'NEW' -- {data}
, (tc.revision + 1)
, 'UPDATE' -- {comment}
, 't' -- {enabled}
, tc.create_time
, now()
FROM text_content tc
LEFT OUTER JOIN text_content mc ON tc.path = mc.path
AND mc.revision > tc.revision
WHERE mc.revision is NULL
AND tc.path = '/stuff' -- {path}
)
Вставляємо за допомогою старих даних. Це особливо корисно, якщо сказати, що ви хотіли оновити лише один стовпець і уникнути оптимістичного блокування та транзакцій.
Підхід прапорця та таблиця історії вимагає вставлення / оновлення двох рядків.
Інша перевага outer join
підходу до редагування номерів полягає в тому, що ви завжди зможете пізніше повернутись до підходу до декількох таблиць за допомогою тригерів, оскільки ваш тригер повинен по суті робити щось подібне до вище.