Пока @WW. Ответ - хороший ответ. Другой способ - создать столбец версий и сохранить все версии в одной таблице.
Для одного стола подходите либо:
- Используйте флаг, чтобы указать последние слова 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
подхода с использованием номера ревизии состоит в том, что вы всегда можете позже выполнить рефакторинг для подхода с несколькими таблицами с помощью триггеров, потому что ваш триггер должен, по существу, делать что-то подобное вышеописанному.