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

标签 sql postgresql prepared-statement triggers

我在 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?

更多选项:
How to UPDATE table from csv file?

关于sql - 如何避免为准备好的语句的每一行启动触发器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23897289/

相关文章:

java - 关于 addBatch(String) 的注意事项

php - 未捕获的异常 'PDOException',消息 'SQLSTATE[HY000]: General error: 20 datatype mismatch' 在/media/Data/Documenten/PHP/µBot/index.php :100

SQL,将同一行中的两列相乘并创建一个 "total"列

java - 是否可以在 Spring Boot 中将 MongoDb 和 PostgreSql 用于同一模型?

sql - 关系 "table"已经存在

php - 有没有办法使用 Db 实例在 prestashop 中准备 sql 语句?

mysql - sql中如何从两个表中获取数据

sql - SSMS:常用查询列表

postgresql - Rails 4 中 PostgreSQL 服务器的默认用户名/密码是什么?

php - 是否可以使用(使用 PHP)先前在 mysql CLI 中声明的准备好的语句?