【问题标题】:Setting NEW.column in "before update" trigger sets values from previous trigger call在“更新前”触发器中设置 NEW.column 设置来自先前触发器调用的值
【发布时间】:2021-10-19 10:31:58
【问题描述】:

我正在尝试为表创建before update 触发器。基本上,在每次更新行时,我都需要在同一张表的同一行上设置额外的列。

但是,由于某种原因,每个触发器调用都会导致设置前一个触发器调用的值。

这是我的触发器的代码:

create or replace function test_trigger_func() returns trigger as $$
    declare
        v_department  text;
    begin
        select department.name into v_department
        from salesprofile
        left join (
           select department.name from salesprofile join department on department.id = (
               salesprofile.solutionscreteria #>> '{departments, 0}'
           )::int4 where salesprofile.id = NEW.id
        ) department on true
        where salesprofile.id = NEW.id
        group by department.name;
        
        NEW.department = v_department;
        
        raise notice 'DEP: %', v_department;
        raise notice 'NEW DEP: %', NEW.department;
        
        return NEW;
    end;
$$ language plpgsql;

drop trigger if exists test_trigger on salesprofile;

create trigger test_trigger before update on salesprofile
for each row execute procedure test_trigger_func();

test_trigger_func 函数内的 select 语句在函数外运行时可以正常工作。但是,当从 test_trigger_func 函数内部调用 select 时,raise notice 语句会显示不正确的(以前的)值。

salesprofile.solutionscreteria #>> '{departments, 0}' 语句包含id 用于department 表中的行。我正在尝试在每个salesprofile 行更新时从"department".name 设置salesprofile 表行上的department 列(通过修改NEW.department = ...)。


我得到的行为:

  • select 语句非常好,可以按预期工作(按原样调用时,在函数外部)。

  • 当我对salesprofile 行进行第一次更新时,触发器将department 列设置为NULL(该列根本不会更新);

  • 当我对salesprofile 行进行第二次更新时,触发器将department 列设置为我在第一次更新时尝试设置的值;

  • 当我对salesprofile 行进行第三次更新时,触发器将department 列设置为我在第二次更新时尝试设置的值;

  • 等等……

  • 如果我把不正确的值放到salesprofile.solutionscreteria #>> '{departments, 0}'值中,第一次触发器更新不会导致任何错误。

  • 然后如果我在此之后设置正确的值,触发器将触发错误(由上一个触发器调用的值不正确引起)。


我不明白这是如何以及为什么会发生的,我希望我能以一种可理解的方式解释这种行为。

这是 potgresql 触发器的预期行为吗?如果没有,您能否解释一下发生了什么以及如何使其正常工作?

【问题讨论】:

  • 这是一个BEFORE 触发器,因此它发生在salesprofile 表具有NEW 数据之前。我没有完全关注,但我想说这个salesprofile.solutionscreteria #>> '{departments, 0}' 使用的是现有(上一个)行,而不是触发器正在运行的更新数据。你试过NEW.solutionscreteria吗?
  • @AdrianKlaver 这确实成功了。您可以将此作为答案发布,我会将其标记为已接受。谢谢!

标签: sql postgresql triggers postgresql-10 postgresql-triggers


【解决方案1】:

这是一个BEFORE 触发器,因此它发生在salesprofile 表具有NEW 数据之前。我没有完全关注,但我想说这个salesprofile.solutionscreteria #>> '{departments, 0}' 使用的是现有(上一个)行而不是触发器正在运行的更新数据。试试NEW.solutionscreteria

【讨论】:

    猜你喜欢
    • 2021-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-31
    • 2016-11-03
    • 2017-10-23
    • 1970-01-01
    • 2013-05-16
    相关资源
    最近更新 更多