条件 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 显示目录中的文件历史记录。
- 1st 运行:首先检查
FOO.doc
并添加其哈希(当时)。 bar.txt
. 同样处理
- 2nd 运行:
FOO.doc
的散列已更改,因此添加了第二个条目。 bar.txt
的条目被单独保留,因为它的哈希值保持不变。
- 第 3 运行:
bar.txt
已删除,FOO.doc
自上次以来保持不变。
- 第 4 运行:
bar.txt
再次添加,FOO.doc
再次保持不变。
关于这个 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')
在 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 显示目录中的文件历史记录。
- 1st 运行:首先检查
FOO.doc
并添加其哈希(当时)。bar.txt
. 同样处理
- 2nd 运行:
FOO.doc
的散列已更改,因此添加了第二个条目。bar.txt
的条目被单独保留,因为它的哈希值保持不变。 - 第 3 运行:
bar.txt
已删除,FOO.doc
自上次以来保持不变。 - 第 4 运行:
bar.txt
再次添加,FOO.doc
再次保持不变。
关于这个 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')