【问题标题】:loop stuck on Trigger postgresql循环卡在 Trigger postgresql 上
【发布时间】:2021-04-18 21:13:40
【问题描述】:

我试图创建一个触发器来控制参数不是 NULL,但是当我尝试插入时:

INSERT INTO puntuacions(puntuacio, contingut, data) VALUES (6,NULL,CURRENT_DATE);

控制台启动一个大循环,试图使 INSERT inside 函数。我不确定我是否必须在函数或触发器结束时执行 INSERT。 BTW on avg select 我试图从 SELECT 中设置一个 AVG 值以插入表中。 我有这个代码:

功能:

create or replace function p_controla() returns trigger as $controla_puntuacions$
begin
IF new.puntuacio IS NULL OR new.contingut IS NULL OR new.data IS NULL
THEN
RAISE 'SIUSPLAU OMPLE TOTES LES DADES DE LA TAULA';
ELSE
INSERT INTO puntuacions(puntuacio, contingut, data) VALUES (new.puntuacio,new.contingut,new.data);
UPDATE continguts SET puntuacio = (SELECT AVG(puntuacio) FROM puntuacions WHERE contingut = new.contingut) WHERE idcontingut = new.contingut;
RAISE ' OK! ';
END IF;
END;
$controla_puntuacions$ language plpgsql;

触发:

create trigger controla_puntuacions
before insert on puntuacions
for each row execute procedure p_controla();

【问题讨论】:

  • 这个触发器基本上实现了一个约束。为什么?
  • 为什么不将这些列定义为NOT NULL

标签: sql postgresql


【解决方案1】:

这个触发器有四个问题:

  1. 您希望INSERT INTO puntuacions 插入一条由触发器处理的记录。触发器不能以这种方式工作。触发函数中的INSERT INTO puntuacions 指示数据库插入另一行。它还将再次触发此触发器并导致无限递归。插入的行位于new 中。 new 中的值将在触发器返回 new 后插入到此表中。
  2. UPDATE continguts 基于 puntuacions 中的数据在插入前触发器中不合适,因为该行尚未插入。
  3. RAISE ' OK! ' 引发异常。因此,即使所有值都不为空,插入也不会正确完成。
  4. 触发器缺少return。当您修复 3 时,这将导致运行时错误。

一个问题是语法for each row execute procedure。这种语法仍然有效,但它是老式的,现在它已被弃用。此处应使用关键字FUNCTION 而不是PROCEDURE

为了更新 continguts,您可以创建一个插入后触发器。 如果要在触发器完成后插入一行,则必须返回new。 如果只想显示“OK”消息,可以使用RAISE NOTICE

可能的解决方案:

插入前触发器的功能:

create or replace function p_controla() returns trigger as $controla_puntuacions$
begin
IF new.puntuacio IS NULL OR new.contingut IS NULL OR new.data IS NULL
THEN
RAISE 'SIUSPLAU OMPLE TOTES LES DADES DE LA TAULA';
ELSE
RAISE NOTICE ' OK! ';
END IF;
RETURN new;
END;
$controla_puntuacions$ language plpgsql;

插入后触发函数:

create or replace function puntuacions_after_ins() returns trigger as $puntuacions_after_ins$
begin
UPDATE continguts SET puntuacio = (SELECT AVG(puntuacio) FROM puntuacions WHERE contingut = new.contingut) WHERE idcontingut = new.contingut;
RETURN new;
END;
$puntuacions_after_ins$ language plpgsql;

插入触发器后:

create trigger puntuacions_after_ins
after insert on puntuacions
for each row execute function puntuacions_after_ins();

after insert 函数中的返回值被忽略,但无论如何这个函数必须返回一些东西。

【讨论】:

    猜你喜欢
    • 2023-03-21
    • 2018-09-27
    • 2023-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多