我找不到应用'高级'基于查询的约束的方法。
例如,使用以下虚构架构,我如何强制执行Bob日常活动的总百分比不超过100%?
我已经调查了trigger constraints但我不认为他们会按照我的意愿行事(如果符合某些条件,则中止INSERT / UPDATE)。
感谢您阅读我的问题以及您可以提供的任何帮助。
create table employee (
id serial PRIMARY KEY,
name varchar(100) NOT NULL
);
create table work_day (
employee_id integer references employee(id) NOT NULL,
percentage integer NOT NULL CHECK (percentage > 0 and percentage <= 100),
activity varchar(100) NOT NULL
);
INSERT INTO employee (name) VALUES ('bob');
-- Bob spends 50% of the day slacking, 20% eating and 30% working (total = 100%)
INSERT INTO work_day (employee_id, percentage, activity) VALUES (1, 50, 'slacking');
INSERT INTO work_day (employee_id, percentage, activity) VALUES (1, 20, 'eating');
INSERT INTO work_day (employee_id, percentage, activity) VALUES (1, 30, 'working');
-- This should be invalid!!! 100% of Bob's time has already been allocated
INSERT INTO work_day (employee_id, percentage, activity) VALUES (1, 10, 'invalid');
答案 0 :(得分:4)
我已经测试了这段代码,但它确实有效:
CREATE OR REPLACE FUNCTION check_work_day_percentage() RETURNS trigger AS $$
BEGIN
IF coalesce((select sum(percentage)
from work_day
where employee_id = NEW.employee_id
and activity != NEW.activity), 0)
+ coalesce(NEW.percentage, 0) > 100 THEN
RAISE EXCEPTION 'Employee % exceeds 100 percent', NEW.employee_id;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER work_day_trigger
BEFORE INSERT OR UPDATE ON work_day
FOR EACH ROW EXECUTE PROCEDURE check_work_day_percentage();
仅供参考,表格约束不会这样做:根据docs,
目前,CHECK表达式不能 包含子查询或参考 除了列之外的变量 当前行。
答案 1 :(得分:0)
基于pl / pgsql的constraint trigger是你想要的。 sum()事物,并检查它是否在定义的范围内。如果没有,raise an exception和声明将被取消。
或者,使用普通触发器存储/更新employee表中的总活动,并对后者设置约束。