【问题标题】:PostgreSQL Update TRIGGER Fires Multiple Times When Just 1 Row UpdatedPostgreSQL Update TRIGGER 在仅更新 1 行时触发多次
【发布时间】:2020-09-17 12:23:48
【问题描述】:

源表:-

CREATE TABLE schema1.Source_Table
(
    Source_Table_id serial NOT NULL,
    current_status_id smallint NOT NULL,
    current_status_reason varchar(200) NULL,
    requestor_id integer NOT NULL,
    approver_id integer NULL,
    last_upd_user_id integer NOT NULL,
    last_upd_date_time timestamp without time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,
    CONSTRAINT PK_Source_Table PRIMARY KEY (Source_Table_id)
)
WITH OIDS;

目标表(审计历史目的):-

CREATE TABLE schema2.Destination_Table
(
    type_id smallint NOT NULL,
    id integer NOT NULL,
    state_id smallint NOT NULL,
    state_reason varchar(200) NULL,
    requestor_id integer NOT NULL,
    approver_id integer NULL,
    upd_by_user_id integer NOT NULL,
    upd_by_user_type smallint NOT NULL,
    upd_date_time timestamp without time zone NOT NULL
)
WITH OIDS;

源表上每个行触发器的更新后:-

CREATE TRIGGER trg_upd_Source_Table
   AFTER UPDATE of current_status_id
   ON schema1.Source_Table
   FOR EACH ROW
  WHEN (OLD.current_status_id IS DISTINCT FROM NEW.current_status_id)
      EXECUTE PROCEDURE schema1.Source_Table_hist();

上面每个行触发器的更新后触发器函数:-

CREATE OR REPLACE FUNCTION schema1.Source_Table_hist()
RETURNS TRIGGER
LANGUAGE PLPGSQL
AS $$
BEGIN
    INSERT INTO schema2.Destination_Table
        (type_id, id, state_id, state_reason, requestor_id, approver_id, upd_by_user_id, 
        upd_by_user_type, upd_date_time)
    SELECT 1, OLD.Source_Table_id, OLD.current_status_id, OLD.current_status_reason, 
        OLD.requestor_id, OLD.approver_id, OLD.last_upd_user_id, 1, OLD.last_upd_date_time
    from schema1.Source_Table
    where OLD.current_status_id IS DISTINCT FROM NEW.current_status_id;
    RETURN NULL;
END;
$$

schema1.Source_Table 表中已有 8 行具有唯一主键 Source_Table_id。 当我使用主键仅更新该表的 1 行时,它会在 schema2.Destination_Table 表中插入 8 行(1 个原始行和 7 个重复行)而不是 1 行。

update schema1.Source_Table
set current_status_id = 4
where Source_Table_id = 9;

这里的问题是:- 为什么触发器会触发 8 次(等于创建此触发器的表中的总行数),而该表仅更新了 1 行。

预期行为:- 当在创建触发器的源表中仅更新 1 行时,触发器应仅触发一次,然后在目标审计表中插入 1 行。

如何解决这个问题?

【问题讨论】:

标签: postgresql triggers sql-update sql-insert


【解决方案1】:

触发器没有多次触发,您的查询正在为源表中的每一行在 hist 表中插入一行:

    INSERT INTO schema2.Destination_Table
    (type_id, id, state_id, state_reason, requestor_id, approver_id, upd_by_user_id, 
    upd_by_user_type, upd_date_time)
SELECT 1, OLD.Source_Table_id, OLD.current_status_id, OLD.current_status_reason, 
    OLD.requestor_id, OLD.approver_id, OLD.last_upd_user_id, 1, OLD.last_upd_date_time
from schema1.Source_Table
where OLD.current_status_id IS DISTINCT FROM NEW.current_status_id;
RETURN NULL;

我认为你不需要那个 from 子句。

【讨论】:

  • 感谢@Jeremy,这是根本原因。删除 from 子句后,它现在可以工作了。
【解决方案2】:

问题在于 WHERE 条件:

where OLD.current_status_id IS DISTINCT FROM NEW.current_status_id

从触发器上的 WHEN 条件可知该条件为真。因为它是唯一的 WHERE 有效,所以它完全没有 WHERE 条件,因此所有 roes 都由插入处理。建议

where current_status_id = OLD.current_status_id

【讨论】:

  • 但是为什么要从表格中选择呢?
猜你喜欢
  • 1970-01-01
  • 2015-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-17
  • 1970-01-01
  • 2015-07-19
  • 1970-01-01
相关资源
最近更新 更多