postgresql - 具有串行字段、规则和错误的 currval / 序列的 PostgreSQL
问题描述
通常使用 PotsgreSQL 根据 CRUD 事件将记录插入日志表需要(至少)一个触发器和一个触发器函数。我尝试使用 Postgres RULES 使其更容易。它几乎可以工作,除了以下场景:
create table mydata ( somedata char(4) , id1 bigserial );
create table mylog ( logid bigint , op char(1), id2 bigserial );
create rule mydata_ilog as on insert to mydata do insert into mylog( logid , op ) values ( new.id1 ,'i' );
insert into mydata( somedata ) values ('0001');
主表和日志表有一个序列字段,我希望 - 在插入一条记录之后mydata
- 在 mydata 中有一条记录,id1=1
在 , 中有一条记录mylog
,其中logid=1
(作为 mydata 记录的 id),并且id2=1
...在mydata
, id1=1
, 对 ... ay mylog
,id2
是 1, 对 ... 但是在mylog
,logid
字段是2
, 并且为递增id1
序列字段而创建的数据库序列是2
...
select currval('mydata_id1_seq'); -- return 2 ?!
select last_value from mydata_id1_seq; -- return 2 ?!
select id1 from mydata -- return 1 ok
select id2 from mydata -- return 1 ok
select logid from mylog -- return 2 ?!
我已经用触发器和触发器功能解决了这个问题,工作正常。但是,PostgreSQL 有什么理由这样做吗?!
解决方案
看执行计划:
EXPLAIN (VERBOSE, COSTS OFF) INSERT INTO mydata (somedata) VALUES ('0001');
QUERY PLAN
------------------------------------------------------------------------------------------------------------
Insert on myschema.mydata
-> Result
Output: '0001'::character(4), nextval('mydata_id1_seq'::regclass)
Insert on myschema.mylog
-> Result
Output: nextval('mydata_id1_seq'::regclass), 'i'::character(1), nextval('mylog_id2_seq'::regclass)
(7 rows)
规则使用用于mydata.id
第二个语句的相同表达式重写查询,因此您nextval
在两个语句中都有调用。
数据修改查询的规则很难做到正确,你只是踏入了一个典型的陷阱。使用触发器。
推荐阅读
- azure - 通过 Azure 逻辑应用监控 200 多个 SFTP 子文件夹
- php - 如何从 2 个不同的列表中交替元素
- ios - 改变 SKNode 的 alpha 没有效果?
- android - 如何将图像(base64 到位图)显示到 Image Slider?
- php - SQLSTATE [23000]:违反完整性约束:1048 列“post_id”不能为空
- javascript - 在循环中使用 Promise 会导致 Promise 失败
- html - CSS变换旋转问题
- visual-studio - 如何在 Visual Studio 2019 项目中恢复我的文件夹?
- php - 提供不同的抽象类在vendor中扩展
- javascript - React - 将 javascript 元素属性向下传递给子组件