条件 CHECK 约束

Conditional CHECK constraint

在 Postgresql 11.5 中,我想要 table 存储文件哈希及其各自的文件名,以及处理此信息的日期。我宁愿将 DELETED! 放入 crc32 列,而不是 available BOOLEAN 列。

像这样table:

 filename |  crc32   |   date
----------+----------+------------
 FOO.doc  | 005929FA | 2015-03-14
 bar.txt  | C5907C6A | 2015-03-14
 FOO.doc  | 2AF317BB | 2016-08-22
 bar.txt  | DELETED! | 2018-11-30
 bar.txt  | AC0132D9 | 2019-09-10

此 table 显示目录中的文件历史记录。

关于这个 table 的事情是,我有一个 CHECK 约束,它只允许将这个正则表达式输入到 crc32 列中:^[0-9A-F]{8}$|^DELETED\!$

我想让这更严格一点。如果文件以前从未在 table 中,我希望 Postgresql 在我尝试使用 DELETED! 时出错。因此,如果我尝试添加如下条目:INSERT INTO hist VALUES ('egg.txt', 'DELETED!', '2019-09-23'); 它将出错。如果我尝试 INSERT INTO hist VALUES ('FOO.doc', 'DELETED!', '2019-09-23'); 它会起作用,因为 FOO.doc 已经存在了。

所以基本上 DELETED! 只能在相关文件在 table.

中已有条目时使用

这可能吗?我希望这是有道理的。如果我没有对此进行足够的解释,请告诉我。谢谢。

最好通过 BEFORE 触发器来满足该附加要求:

CREATE FUNCTION check_upd() RETURNS trigger
   LANGUAGE plpgsql AS
$$BEGIN
   IF NOT EXISTS (SELECT 1 FROM my_table
                  WHERE filename = NEW.filename)
   THEN
      RAISE EXCEPTION 'cannot delete a non-existing row';
   END IF;

   RETURN NEW;
END;$$;

CREATE TRIGGER check_upd BEFORE INSERT ON my_table
   FOR EACH ROW WHEN (NEW.crc32 = 'DELETED!')
EXECUTE PROCEDURE check_upd();

我添加了这个 CHECK 约束,它似乎有效。

CHECK (crc32 IS NULL AND is_deleted = 't' OR crc32 IS NOT NULL AND is_deleted = 'f')