验证子查询计数不大于x

时间:2014-11-10 22:58:49

标签: sql postgresql triggers plpgsql

我正在尝试创建一个函数和一个触发器,用于验证wid表中rdateresponsibility列的计数是否小于或等于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();

1 个答案:

答案 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;

确保widrdate上的索引,或理想情况下,(wid, rdate)上的多列索引。