我在 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();
我必须按如下方式更新该表的行:
UPDATE table1 SET field1='abc' WHERE field5=1;
UPDATE table1 SET field1='def' WHERE field5=2;
UPDATE table1 SET field1='ghi' WHERE field5=3;
...
为了清楚起见,名称和值都进行了简化。
每个 UPDATE
都被视为一个语句,因此触发器会为这些行中的每一行触发。
为了避免这种情况,我做了一个准备好的声明:
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);
我原以为只有在准备好的语句完成后才会触发触发器,但没有,触发器会针对每个 EXECUTE
行触发。
问题是触发过程需要时间来执行。 有解决这个问题的想法吗?
最佳答案
在带有 VALUES
expression 的子查询中提供多行使其成为单个 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;
您需要转换为匹配类型,因为 VALUES
表达式是独立的,不能像 UPDATE 中那样派生列类型。没有引号的只有数字的数字默认为 integer
(bigint
/numeric
如果太大)。
您仍然可以使用准备好的语句(带有许多参数)。对于大量行,宁愿切换到批量加载到临时暂存表并从那里更新:
How to update selected rows with values from a CSV file in Postgres?
关于sql - 如何避免为准备好的语句的每一行启动触发器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23897289/