Function 使用触发器检查每个值是否已超过PostgreSQL中的限制,并发出通知

Function 使用触发器检查每个值是否已超过PostgreSQL中的限制,并发出通知,function,postgresql,triggers,Function,Postgresql,Triggers,我想在这里得到的是哪个科目已经有4个教室,如果超过了,请发出通知并返回null,然后开始工作。但当我插入其他主题“2”时,代码引起了同样的注意,但我这个主题只有1个classrom。我知道我使用的是“HAVING COUNT(cod_教室)=4”,而代码只得到科目已经有4个教室的内容。我试着只使用这个:“选择不同的cod\u主题,COUNT(cod\u教室)作为cod\u主题组中的CountOf,按cod\u主题”但我不知道如何检查更多值 我希望你们都明白我想要什么,我已经尽了最大的努力了 CR

我想在这里得到的是哪个科目已经有4个教室,如果超过了,请发出通知并返回null,然后开始工作。但当我插入其他主题“2”时,代码引起了同样的注意,但我这个主题只有1个classrom。我知道我使用的是“
HAVING COUNT(cod_教室)=4
”,而代码只得到科目已经有4个教室的内容。我试着只使用这个:“
选择不同的cod\u主题,COUNT(cod\u教室)作为cod\u主题组中的CountOf,按cod\u主题
”但我不知道如何检查更多值

我希望你们都明白我想要什么,我已经尽了最大的努力了

CREATE OR REPLACE FUNCTION quantas()
      RETURNS trigger AS
    $BODY$declare qtd record;

    begin

    SELECT * INTO qtd FROM (SELECT DISTINCT cod_subject,COUNT(cod_classroom) AS CountOf FROM registration_subject 
    GROUP BY cod_subject HAVING COUNT(cod_classroom) = 4) AS total;

    if found then

    raise notice 'This subject has already 4 classroom';

    return null;

    end if;

    end;$BODY$
      LANGUAGE plpgsql VOLATILE
      COST 100;
    ALTER FUNCTION qtd()
      OWNER TO postgres;

除了Craig在评论中提到的问题(需要锁定独占模式),我认为您还有一些其他问题

你的问题就是这样,对我来说没有多大意义

  SELECT * INTO qtd 
    FROM (SELECT DISTINCT cod_subject,COUNT(cod_classroom) AS CountOf 
           FROM registration_subject 
GROUP BY cod_subject HAVING COUNT(cod_classroom) = 4) AS total;
我不认为这是一种非常有用的查询方式。事实上,只要任何科目有4个教室,它就相当有帮助地拒绝了所有插入

相反,我建议:

    PERFORM count(cod_classroom)
       FROM registration_subject
      WHERE cod_subject = NEW.subject
     HAVING count(*) >= 4;

PERFORM
在plpgsql中用于不关心使用结果的情况。在这里,你只关心它是否被找到。第二,如果出现错误,允许错误插入,您仍然会阻止后续插入。如果任何科目正好有四个课室,您的旧代码将阻止插入所有科目,但5个课室是可以的,这也不是您想要的。

如果不添加适当的
LOCK
语句,此函数容易出现争用条件,这意味着它将在并发删除时错误地拒绝合法更改,并错误地允许多次插入。您必须在独占模式下锁定
注册\u主题
,以获得可靠的结果。采取
选择。。。对于共享
行锁不足以防止并发插入。