使用 plpgsql 更新函数中的列

Posted

技术标签:

【中文标题】使用 plpgsql 更新函数中的列【英文标题】:Update a column in a function using plpgsql 【发布时间】:2017-03-19 18:44:18 【问题描述】:

我正在 PostgreSQL 9.5 中编写一个触发器函数。当名为action_flag 的列从FALSE 更新为TRUE 时,会调用一个函数。

如果order_num 在某个表中,那么我希望继续从FALSE 更新到TRUE

否则,如果order_num 在其他表中,那么我想引发异常并阻止更新发生。

我需要在我的 IF 声明中编写 UPDATE 的帮助。 ELSEIF 部分按预期运行。

CREATE OR REPLACE FUNCTION check_ingredient_availability()
RETURNS TRIGGER AS 
$Body$
BEGIN
    if (OLD.order_num IN ( SELECT  order_num
                   FROM    can_prep_m_orders )) THEN
        RAISE NOTICE 'This is a notice.';
        --UPDATE meal_order
        --SET actioned_flag=TRUE
        --WHERE order_num=OLD.order_NUM;

        --EXECUTE  'UPDATE  meal_order
            -- SET   actioned_flag=TRUE
             --WHERE     order_num=$1' 
             --USING OLD.order_num;
        RETURN NULL;
    ELSEIF (OLD.order_num IN ( SELECT  order_num
                        FROM    cannot_prep_m_orders )) THEN
        RAISE EXCEPTION 'Missing ingredients. Cannot prepare order number %.',
                OLD.order_num;
        RETURN NULL;
    ELSE
        RETURN NULL;
    END IF;
END;    
$Body$ LANGUAGE plpgsql;

【问题讨论】:

【参考方案1】:

使用EXISTS

CREATE OR REPLACE FUNCTION check_ingredient_availability()
   RETURNS TRIGGER AS 
$func$
BEGIN
   IF EXISTS (
         SELECT 1 FROM can_prep_m_orders
         WHERE  order_num = NEW.order_num  -- NEW !?
         ) THEN
      RAISE NOTICE 'This is a notice.';

      -- do nothing, let original UPDATE proceed

      RETURN NEW;   -- let UPDATE proceed
   END IF;

   IF EXISTS (
         SELECT 1 FROM cannot_prep_m_orders
         WHERE  order_num = NEW.order_num  -- NEW!?
         ) THEN

      RAISE EXCEPTION 'Missing ingredients. Cannot prepare order number %.', NEW.order_num;
                                       -- I assume you want to mention the *new* order_num?
   END IF;

   RETURN NULL;  -- cancel original UPDATE in all other cases
END
$func$  LANGUAGE plpgsql;

相关:

PL/pgSQL checking if a row exists - SELECT INTO boolean

另外,在触发器中添加 WHEN 子句,以便在何时运行这些检查

action_flagFALSE 更新为TRUE

CREATE TRIGGER your_trigger_name
BEFORE UPDATE ON your_table
FOR EACH ROW 
WHEN (NEW.action_flag AND NOT OLD.action_flag)
EXECUTE procedure check_ingredient_availability();

相关:

Trigger with multiple WHEN conditions

【讨论】:

感谢您的回复,欧文。这很有帮助!我不知道 RETURN NEW;是什么允许更新继续进行。 @Pizzas: Consider reading this chapter of the manual.

以上是关于使用 plpgsql 更新函数中的列的主要内容,如果未能解决你的问题,请参考以下文章

尝试使用 RETURNING 和更新/插入从 plpgsql 函数返回时出错

无法执行 plpgsql/postgres 中的函数

如何使用 plpgsql 函数插入数据?

后记。超出 plpgsql 堆栈深度限制

如何在执行 SELECT... 语句时将表列传递给 plpgsql 函数

Postgresql:对 plpgsql 中的临时表执行更新不起作用