【问题标题】:Writing an SQL trigger to find if number appears in column more than X times?编写 SQL 触发器来查找列中出现的数字是否超过 X 次?
【发布时间】:2023-03-30 00:43:02
【问题描述】:

我想编写一个 Postgres SQL 触发器,它基本上会发现一个数字是否在列中出现 5 次或更多次。如果它出现第五次,我想抛出一个异常。以下是表格的外观:

create table tab(
first integer not null constraint pk_part_id primary key,
second integer constraint fk_super_part_id references bom,
price integer);

insert into tab values(1,NULL,100), (2,1,50), (3,1,30), (4,2,20), (5,2,10), (6,3,20);

以上是表格中的原始插入。我的触发器将在向表中插入更多值时发生。

基本上,如果一个数字在插入表格后出现在“第二”列中超过 4 次,我想引发异常。这是我编写触发器的尝试:

create function check() return trigger as '
begin
    if(select first, second, price
          from tab
          where second in (
            select second from tab
            group by second
            having count(second) > 4)
) then
raise exception ''Error, there are more than 5 parts.'';
end if;
return null;
end 
'language plpgsql;

create trigger check
after insert or update on tab
for each row execute procedure check();

谁能帮帮我?如果是这样那就太好了!谢谢!

【问题讨论】:

  • 你为什么要这个?你想解决什么问题?
  • 这听起来像是应该在前端,在数据库之外处理的业务逻辑。
  • 只是为了了解 SQL 触发器。我想实现自己的。

标签: sql postgresql triggers plpgsql


【解决方案1】:
CREATE FUNCTION trg_upbef()
  RETURN trigger as
$func$
BEGIN
IF (SELECT count(*) 
    FROM   tab
    WHERE  second = NEW.second ) > 3 THEN

   RAISE EXCEPTION 'Error: there are more than 5 parts.';
END IF;

RETURN NEW;  -- must be NEW for BEFORE trigger

END
$func$ LANGUAGE plpgsql;

CREATE TRIGGER upbef
BEFORE INSERT OR UPDATE ON tab
FOR EACH ROW EXECUTE procedure trg_upbef();

要点

  • 关键字是RETURNS,而不是RETURN

  • 使用special variable NEW 来引用新插入/更新的行。

  • 使用BEFORE 触发器。发生异常时最好尽早跳过。

  • 不要把一切都算在你的测试中,只需要你需要的。 快得多

  • 使用dollar-quoting。让您的生活更轻松。

  • 并发:
    如果您想绝对确定,则必须在计数之前对表进行排他锁。否则,并发插入/更新可能会在并发负载较重的情况下相互超越。虽然这不太可能,但有可能。

【讨论】:

  • 你把 > 3 放在 if 语句后面有什么原因吗?
  • @user1871869:这不是 IF 声明之后,真的。就在SELECT 声明之外。在这种情况下,与count(*) 的比较也可以进入内部。甚至会快一点。我没有像您那样将整个 IF 表达式括在括号中。那只是噪音。
  • 很有意义。谢谢!我遇到了 RETURN 语句的问题......我把 return 而不是 return..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-13
  • 1970-01-01
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
  • 2017-11-26
相关资源
最近更新 更多