Podczas gdy @WW. odpowiedź jest dobrą odpowiedzią innym sposobem jest utworzenie kolumny wersji i trzymanie wszystkich wersji w tej samej tabeli.
Przy jednym stoliku podejdź do Ciebie:
- Użyj flagi, aby wskazać najnowszy ala Word Press
- LUB zrób paskudną wersję większą niż
outer join
.
Przykładowy kod SQL outer join
metody używającej numerów wersji to:
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.
Zła wiadomość jest taka, że powyższe wymaga, outer join
a łączenia zewnętrzne mogą być powolne. Dobra wiadomość jest taka, że tworzenie nowych wpisów jest teoretycznie tańsze, ponieważ można to zrobić w jednej operacji zapisu bez transakcji (zakładając, że baza danych jest atomowa).
Przykładem tworzenia nowej wersji dla '/stuff'
może być:
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}
)
Wstawiamy przy użyciu starych danych. Jest to szczególnie przydatne, jeśli chcesz zaktualizować tylko jedną kolumnę i uniknąć optymistycznego blokowania i / lub transakcji.
Podejście z flagami i podejście do tabeli historii wymagają wstawienia / aktualizacji dwóch wierszy.
Inną zaletą outer join
podejścia opartego na numerach wersji jest to, że zawsze możesz później zmienić podejście do podejścia z wieloma tabelami z wyzwalaczami, ponieważ wyzwalacz powinien zasadniczo wykonywać coś podobnego do powyższego.