基于SELECT条件的postgres约束

时间:2018-03-20 22:23:58

标签: postgresql constraints

ᕼello!我认为我有一些棘手的事情:

parentchild个人。 child有一个age,还有一个标记为appreciated

规则:父母不能欣赏两个同龄孩子!

我的问题是:如何执行此规则

当前架构:

CREATE TABLE parent (
  id SERIAL PRIMARY KEY,
  name VARCHAR(50) NOT NULL
);

CREATE TABLE child (
  id SERIAL PRIMARY KEY,
  parent INTEGER REFERENCES parent(id) NOT NULL,
  name VARCHAR(50) NOT NULL,
  age INTEGER NOT NULL,
  appreciated BOOLEAN NOT NULL
);

将一些值放入:

INSERT INTO parent(name) VALUES
  ('bob'),    -- assume bob's id = 0
  ('mary');   -- assume mary's id = 1

INSERT INTO child(parent, name, age, appreciated) VALUES
  (0, 'child1', 10, FALSE), -- Bob has children 1, 2, 3
  (0, 'child2', 10, FALSE),
  (0, 'child3', 15, FALSE),
  (1, 'child4', 20, FALSE), -- Mary has children 4, 5, 6
  (1, 'child5', 20, FALSE),
  (1, 'child6', 10, FALSE);

到目前为止一切都很好。没有孩子受到赞赏,这总是有效的。

允许玛丽欣赏孩子6:

UPDATE child SET appreciated=TRUE WHERE name='child6';

鲍勃被允许欣赏child2。 child2与child6(已被欣赏)的年龄相同,但child6不是Bob的孩子。

UPDATE child SET appreciated=TRUE WHERE name='child2';

Bob现在无法欣赏child1。这个child1与child2的年龄相同,child2已经被赞赏了。

UPDATE child SET appreciated=TRUE WHERE name='child2'; -- This needs to FAIL!

如何执行此类约束?我对各种解决方案持开放态度,但修改通用模式不是一种选择。

提前致谢!

3 个答案:

答案 0 :(得分:3)

UNIQUE部分索引如何:

CREATE UNIQUE INDEX ON child(parent,age) WHERE appreciated;

所以每一对parentage都必须是唯一的,但只有在被尊重的孩子被考虑时才会这样。

答案 1 :(得分:1)

您可能希望使用在插入/更新之前激活的触发器,如果​​不满足您创建的约束,则会失败。 我想它应该像

create trigger <trigger_name>
before insert or update on <table_name>
for each row
declare
dummy number;
begin
select count(*)
into dummy
from <table_name>
where (appreciated=TRUE and :new.child = child and :new.age = age);

if dummy > 0 then
  raise_application_error(-20001,'Too many appreciated children');
end if;
end;

Some documentation

答案 2 :(得分:0)

我想要做的最简单的事情是向父模型添加一个感恩(?)== false的标志,当child.appreciated == true {parent.grateful == true}

检查作用于child.appreciated的函数中parent.grateful的值。 如果parent.grateful == true  返回&#34;抱歉,这位家长已表示感谢。&#34; 大声笑这是一个有趣的概念。祝好运。 :)