简体   繁体   English

PostgreSQL 更新 TRIGGER 在仅更新 1 行时触发多次

[英]PostgreSQL Update TRIGGER Fires Multiple Times When Just 1 Row Updated

Source Table :-源表:-

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;

Destination Table (Audit History Purpose) :-目标表(审计历史目的):-

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;

After Update for each Row Trigger on the Source Table :-更新源表上的每个行触发器后:-

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();

Trigger Function for the After Update for each Row Trigger above :-上面每个行触发器的更新后的触发器函数:-

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;
$$

There are already 8 rows in schema1.Source_Table table with the unique primary key Source_Table_id. schema1.Source_Table 表中已经有 8 行具有唯一的主键 Source_Table_id。 When I update just 1 row of this table as below using the primary key, it inserts 8 rows (1 original and 7 duplicates) into the schema2.Destination_Table table instead of just 1 row.当我使用主键更新此表的 1 行时,如下所示,它将 8 行(1 个原始行和 7 个副本)插入到 schema2.Destination_Table 表中,而不是仅插入 1 行。

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

The issue here is :- Why the trigger is firing for 8 times (which is equals to the total number of rows in the table on which this trigger is created) when only 1 row of that table is updated.这里的问题是:-当仅更新该表的 1 行时,为什么触发器会触发 8 次(这等于在其上创建此触发器的表中的总行数)。

Expected Behavior :- The Trigger should fire only once followed by inserting 1 row in the destination audit table when just 1 row is updated in the source table on which the trigger is created.预期行为:-触发器应仅触发一次,然后在创建触发器的源表中仅更新 1 行时,在目标审计表中插入 1 行。

How to solve this issue ?如何解决这个问题?

The trigger isn't firing multiple times, your query is inserting a row into the hist table for every row in the source table:触发器不会多次触发,您的查询正在为源表中的每一行在 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;

I don't think you need that from clause.我认为你不需要那个 from 子句。

The problem is in the WHERE condition:问题出在 WHERE 条件中:

where OLD.current_status_id IS DISTINCT FROM NEW.current_status_id

This condition is known to be true from the WHEN condition on the trigger.根据触发器上的 WHEN 条件,已知此条件为真。 As it is the only WHERE effective it is the same no WHERE condition at all, there fore all roes are processed by the insert.因为它是唯一有效的 WHERE,所以完全没有 WHERE 条件,因此所有鱼子都由插入物处理。 Suggest建议

where current_status_id = OLD.current_status_id

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM