Я экспериментирую с созданием таблицы, в которой хранится версия каждой строки. Идея состоит в том, чтобы иметь возможность запрашивать, как строки были в любой момент времени, даже если запрос имеет JOIN. Рассмотрим систему, в которой основным ресурсом являются книги, то есть запрашиваются книги, а информация об авторе приходит вместе с вами
CREATE TABLE authors (
author_id INTEGER NOT NULL,
version INTEGER NOT NULL CHECK (version > 0),
author_name TEXT,
is_active BOOLEAN DEFAULT '1',
modified_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (author_id, version)
)
INSERT INTO authors (author_id, version, author_name)
VALUES (1, 1, 'John'),
(2, 1, 'Jack'),
(3, 1, 'Ernest');
Я бы хотел обновить вышеперечисленное, вот так
UPDATE authors SET author_name = 'Jack K' WHERE author_id = 1;
и в итоге
2, 1, Jack, t, 2012-03-29 21:35:00
2, 2, Jack K, t, 2012-03-29 21:37:40
, который я могу затем запросить с помощью
SELECT author_name, modified_on
FROM authors
WHERE
author_id = 2 AND
modified_on < '2012-03-29 21:37:00'
ORDER BY version DESC
LIMIT 1;
чтобы получить
2, 1, Jack, t, 2012-03-29 21:35:00
Что-то вроде следующего не работает
CREATE OR REPLACE FUNCTION archive_authors() RETURNS TRIGGER AS $archive_author$
BEGIN
IF (TG_OP = 'UPDATE') THEN
-- The following fails because author_id,version PK already exists
INSERT INTO authors (author_id, version, author_name)
VALUES (OLD.author_id, OLD.version, OLD.author_name);
UPDATE authors
SET version = OLD.version + 1
WHERE
author_id = OLD.author_id AND
version = OLD.version;
RETURN NEW;
END IF;
RETURN NULL; -- result is ignored since this is an AFTER trigger
END;
$archive_author$ LANGUAGE plpgsql;
CREATE TRIGGER archive_author
AFTER UPDATE OR DELETE ON authors
FOR EACH ROW EXECUTE PROCEDURE archive_authors();
Как мне достичь вышеуказанного? Или есть лучший способ сделать это? В идеале я бы предпочел не создавать теневую таблицу для хранения заархивированных строк.