我正在尝试创建一个函数和一个触发器,用于验证wid
表中rdate
和responsibility
列的计数是否小于或等于10.我需要当它超过10时引发异常。
我的子查询计数不起作用。当COUNT()
大于10时,不会抛出任何异常
我做错了什么?
CREATE FUNCTION check_10() RETURNS TRIGGER AS $$
BEGIN
IF (SELECT COUNT(CASE WHEN wid = NEW.wid AND rdate = NEW.rdate THEN 1 ELSE 0 END) AS total FROM resposibility) > 10 THEN
RAISE EXCEPTION 'MAXIMUM OF 10 CAGE RESPONSIBILITES FOR EACH WORKER PER DATE';
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
/* I've added update to make sure even when "updating" that row it will run the trigger check to verify */
CREATE TRIGGER insert_resp BEFORE INSERT OR UPDATE ON resposibility
FOR EACH ROW EXECUTE PROCEDURE check_10();
答案 0 :(得分:1)
只要您提出EXCEPTION
(并且没有抓住它),无论如何都会立即回滚整个交易。在这种情况下,RETURN
语句无关紧要。删除它。
如果您想静默跳过当前行上的操作,否则使用RETURN NULL
代替 替代
代码中唯一明显的错误是> 10
而不是 >= 10
as pointed out by @a_horse。和resposibility
中的拼写错误。剩下的就是效率问题。
另外,在plpgsql中,赋值相对较贵,这里真的没有必要。简化:
CREATE OR REPLACE FUNCTION check_10()
RETURNS TRIGGER AS
$func$
BEGIN
IF (SELECT count(*) >= 10
FROM responsibility
WHERE wid = NEW.wid
AND rdate = NEW.rdate) THEN
RAISE EXCEPTION 'WORKER % ALREADY HAS MAX. OF 10 RESPONSIBILITES FOR DATE: %'
, NEW.wid, NEW.rdate;
-- no need for *any* RETURN statement here!
END IF;
RETURN NEW;
END
$func$ LANGUAGE plpgsql;
确保wid
和rdate
上的索引,或理想情况下,(wid, rdate)
上的多列索引。