微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

PostgreSQL 两表常量无法正常工作

如何解决PostgreSQL 两表常量无法正常工作

我运行以下代码

-- Table describing messages
CREATE TABLE messages
(
 id serial PRIMARY KEY NOT NULL,text TEXT  -- Message can have or not have text
);

-- Table describing media attached to messages
CREATE TABLE messages_attachments
(
 message_id integer NOT NULL REFERENCES messages,-- Messages can have any number of attachments,including 0
 attachment_id TEXT NOT NULL
);

-- Messages must have either text or at least one attachment
CREATE FUNCTION message_has_text_or_attachments(integer) RETURNS bool STABLE
AS
$$
 SELECT
  EXISTS(SELECT 1 FROM messages_attachments WHERE message_id = $1)
 OR
  (SELECT text IS NOT NULL FROM messages WHERE id = $1);
$$ LANGUAGE sql;

ALTER TABLE messages ADD CONSTRAINT nonempty_message CHECK ( message_has_text_or_attachments(id) );

-- Insert a message with no text and no attachments. Should fail,but it does not
INSERT INTO messages(text) VALUES (NULL);

SELECT *,message_has_text_or_attachments(id) FROM messages;

我预计它会在 INSERT 行失败,因为插入的行违反了检查约束(我们正在插入文本为 NULL 的消息并且该消息没有附件),但是它运行成功,下一个查询返回 (1,NULL,false)(这里是一个 example 稍微修改函数定义(撇号而不是美元符号,因为数据库版本)。

更有趣的事情是,如果我在添加 INSERT 之前更改命令的顺序和 CONSTRAINT 行,那么 Postgresql 无法 ALTER 表,因为“{{ 1}}”。

为什么Postgresql允许插入违反约束的行?我在函数定义的某个地方弄错了吗?关于如何应用约束以及它们可以依赖哪些表是否有一些限制?是 Postgresql错误吗?

解决方法

来自the docs

PostgreSQL 不支持引用表数据的 CHECK 约束,而不是被检查的新行或更新行。虽然违反此规则的 CHECK 约束在简单测试中可能看起来有效,但它不能保证数据库不会达到约束条件为假的状态(由于涉及的其他行的后续更改)。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。