Database Design Advice
Dagfinn Ilmari Mannsåker
ilmari at ilmari.org
Sun Nov 17 22:12:28 GMT 2013
Smylers <Smylers at stripey.com> writes:
> Here it is in Postgres's own function language, which goes by the
> awkwardly written name PL/pgSQL:
>
> CREATE OR REPLACE FUNCTION set_document_version_num() RETURNS TRIGGER AS
> $FN$
> BEGIN
> NEW.version := 1 +
> MAX(version)
> FROM document_version
> WHERE document_id = NEW.document_id;
> RETURN NEW;
> END;
> $FN$ LANGUAGE plpgsql;
>
> CREATE TRIGGER insert_document_version_num
> BEFORE INSERT ON document_version FOR EACH ROW
> EXECUTE PROCEDURE set_document_version_num();
This trigger works fine, until you get concurrent saves of the same
document, in which case one of the transactions will get a duplicate key
violation. If you want both to succed, with the last one winning, you
can do it by keeping the current version in the document table, and
making the trigger update it:
ALTER TABLE document
ADD COLUMN current_version INTEGER NOT NULL DEFAULT 0;
-- If you already have document versions in the database
UPDATE document
SET current_version = v.max_version
FROM (
SELECT document_id, MAX(version) max_version
FROM document_version group by document_id
) v
WHERE document.id = v.document_id;
REPLACE FUNCTION set_document_version_num() RETURNS TRIGGER AS
$FN$
BEGIN
UPDATE document
SET current_version = current_version + 1
WHERE id = NEW.document_id
RETURNING current_version
INTO NEW.version;
RETURN NEW;
END
$FN$ LANGUAGE plpgsql;
--
- Twitter seems more influential [than blogs] in the 'gets reported in
the mainstream press' sense at least. - Matt McLeod
- That'd be because the content of a tweet is easier to condense down
to a mainstream media article. - Calle Dybedahl
More information about the london.pm
mailing list