我正在尝试创建一个保存每行版本的表。我们的想法是能够查询行在任何时间点的行,即使查询具有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();
我如何实现上述目标?或者,有没有更好的方法来实现这一目标?理想情况下,我宁愿不创建影子表来存储存档的行。
答案 0 :(得分:2)
使用BEFORE UPDATE触发器(而不是AFTER UPDATE)相对容易。
但这也意味着您必须手动确保在该表的所有其他BEFORE UPDATE触发器之后触发归档触发器。触发器按字母顺序触发。
答案 1 :(得分:0)
我无法想出一个替代你的方法,可能是不同的执行,但基本的想法将IMO始终是相同的。如果您希望能够使用上面显示的用于查询特定版本的查询,则必须坚持使用单个表和发布的触发器。
你也许也可以考虑这个问题:拥有一个表authors_revisions
来存储你需要的所有修订版(触发器略有改动)。因此,原始表将始终具有最多tp-date条目。您可以创建一个连接两个表的视图,以便执行上面显示的查询。这样,您的主表不会与旧版本混在一起。
答案 2 :(得分:0)
不要使用触发器并插入而不是更新:
insert into authors (author_id, version, author_name)
select
1,
(
select max(version) + 1
from authors
where author_id = 1
),
'Jack K'
BTW为什么有时间戳的版本号?