简体   繁体   English

如何避免为准备好的语句的每一行启动触发器?

[英]How to avoid launching a trigger for every row of a prepared statement?

I have a FOR EACH STATEMENT trigger on table1 : 我在table1上有一个FOR EACH STATEMENT触发器:

CREATE TRIGGER trg_table1 AFTER INSERT OR DELETE OR UPDATE OF field1 ON table1
FOR EACH STATEMENT EXECUTE PROCEDURE my_trigger_procedure();

I have to update rows of that table as follows: 我必须按如下方式更新该表的行:

UPDATE table1 SET field1='abc' WHERE field5=1;
UPDATE table1 SET field1='def' WHERE field5=2;
UPDATE table1 SET field1='ghi' WHERE field5=3;
...

Names and values are simplified for clarity. 为了清楚起见,名称和值被简化。

Each UPDATE is considered a single statement, so the trigger is fired for every one of those rows. 每个UPDATE被视为一条语句,因此将为这些行中的每一行触发该触发器。

To avoid that, I made a prepared statement: 为了避免这种情况,我做了准备发言:

PREPARE my_prep_stmnt AS
UPDATE table1
SET
field1=$1
WHERE field5=$2
;

EXECUTE my_prep_stmnt ('abc',1);
EXECUTE my_prep_stmnt ('def',2);
EXECUTE my_prep_stmnt ('ghi',3);

I was expecting the trigger to be fired only after the prepared statement was done, but no, the trigger is fired for every EXECUTE row. 我期望仅在准备好的语句完成后才触发触发器,但不,触发器针对每个EXECUTE行都触发。

The problem is that the trigger procedure takes time to execute. 问题是触发过程需要时间才能执行。 Any idea to go around this ? 有什么想法可以解决吗?

Provide multiple rows in a subquery with a VALUES expression to make it a single UPDATE statement: 在子查询中使用VALUES表达式提供多行以使其成为单个 UPDATE语句:

UPDATE table1 t
SET    field1 = u.field1
FROM (
   VALUES
    ('abc'::text, 1)   -- cast string literal in row 1 to make type unambiguous
   ,('def', 2)
   ,('ghi', 3)
   ) u (field1, filed5)
WHERE  t.field5 = u.field5;

You need to cast to a matching type, since the VALUES expressions stands alone and cannot derive the column type like in the UPDATE. 您需要强制转换为匹配类型,因为VALUES表达式是独立的,不能像UPDATE中那样派生列类型。 Unquoted numbers with just digits default to integer ( bigint / numeric if too big). 仅带数字的未加引号的数字默认为integerbigint / numeric如果太大)。

You can still use a prepared statement (with many parameters). 您仍然可以使用准备好的语句(带有许多参数)。 For a large number of rows rather switch to bulk loading to a temporary staging table and update from there: 对于大量行,请改用批量加载到临时登台表并从那里进行更新:
How to update selected rows with values from a CSV file in Postgres? 如何使用Postgres中CSV文件中的值更新所选行?

More options: 更多选择:
How to UPDATE table from csv file? 如何从csv文件更新表?

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

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