在CTE中使用set_config

问题描述 投票:0回答:1

我希望能够调用

set_config
在与 INSERT 语句相同的事务/范围内设置配置参数。插入后会触发一个函数,该函数会从此配置参数中读取数据。

我需要将其作为单个语句来完成,因此 CTE 似乎是一个好主意:

WITH 
  idx AS (SELECT set_config('audit.trace_id', '123', true)), 
  rows AS (INSERT INTO "person" ("name") values ('Mary') RETURNING *) 
SELECT * FROM rows

但是,似乎

audit.trace_id
无法用于触发功能。所以我想我应该像下面这样构造它,这应该创建一个依赖项:

WITH 
  idx AS (SELECT set_config('audit.trace_id', '123', true)) 
INSERT INTO "person" ("name") values ('Mary') RETURNING *

但是,

audit.trace_id
中的值仍然没有设置在触发函数的范围内。我相信这是因为 Postgre 避免运行 SELECT,因为结果不需要进一步进入 CTE。

如果我从两者中选择,如下所示,则当触发函数运行时

audit.trace_id
已成功设置:

WITH 
  idx AS (SELECT set_config('audit.trace_id', '123', true) as __trace_id),
  row as (INSERT INTO "person" ("name") values ('Mary') RETURNING *)
SELCET * FROM idx, row

问题

“audit.trace_id”是否保证在触发器在 person 表上执行时设置?或者这里是否存在可能的竞争条件?

编辑:

这个呢?看起来效果不错:

INSERT INTO "person" ("name") values ('Mary') RETURNING *, set_config('audit.trace_id', '123', true)
postgresql common-table-expression
1个回答
0
投票

在 PostgreSQL 中,在公用表表达式 (CTE) 中,不保证查询按照编写的顺序执行,它们由 PostgreSQL 引擎优化,并且可能并行执行或以不同的顺序执行。不出所料。
但是,WITH

中的数据修改语句只执行一次,并且始终完成,这意味着它们始终会在主查询开始运行之前完全完成。

考虑到您的限制和您面临的问题,您提出的最终解决方案似乎是:

INSERT INTO "person" ("name") values ('Mary') RETURNING *, set_config('audit.trace_id', '123', true)
将是确保在触发器函数执行之前设置配置参数

'audit.trace_id'

的最可靠方法,因为它在
INSERT
语句的
RETURNING
子句中设置配置参数,本质上使其成为数据修改语句的一部分,确保它在同一事务内且在任何 
AFTER INSERT
 触发之前执行。

© www.soinside.com 2019 - 2024. All rights reserved.