条件检查约束

时间:2019-09-23 10:12:15

标签: sql postgresql sql-insert check-constraints

在Postgresql 11.5中,我希望有一个表存储文件散列及其各自的文件名,以及有关何时处理此信息的日期。与其使用available BOOLEAN列,不如将DELETED!放在crc32列中。

像这张桌子一样:

 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

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

  • 第一次运行:FOO.doc首先被检查,并添加了其哈希值(当时)。与bar.txt相同。
  • 第二次运行:FOO.doc的哈希值已更改,因此添加了第二个条目。 bar.txt的条目被保留,因为其哈希值保持不变。
  • 第三轮比赛:bar.txt被删除,FOO.doc自上次以来未受影响。
  • 第四轮:bar.txt被再次添加,FOO.doc再次保持不变。

关于此表的问题是,我有一个CHECK约束,该约束仅允许将此正则表达式输入到crc32列中:^[0-9A-F]{8}$|^DELETED\!$

我想对此进行更严格的规定。如果文件以前从未存在于表中,我希望在尝试使用DELETED!时出现Postgresql错误。因此,如果我尝试添加类似INSERT INTO hist VALUES ('egg.txt', 'DELETED!', '2019-09-23');的条目,则会出错。如果我尝试INSERT INTO hist VALUES ('FOO.doc', 'DELETED!', '2019-09-23');,它将因为FOO.doc已经存在而起作用。

因此,DELETED!基本上只能在有关文件在表中已经有条目的情况下使用。

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

2 个答案:

答案 0 :(得分:1)

最好使用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();

答案 1 :(得分:0)

我添加了此CHECK约束,它似乎可以正常工作。

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