用延迟约束违反外键约束

时间:2020-06-09 16:16:17

标签: sql node.js postgresql

我正在尝试将sql脚本设置为事务,以实现数据库的原子性。

表结构(简化):

CREATE TABLE foo (
    id serial  NOT NULL,
    foo varchar(50)  NOT NULL,    
    CONSTRAINT foo_pk PRIMARY KEY (id)
);

CREATE TABLE access (
    id serial  NOT NULL,
    foo_id int  NULL
    CONSTRAINT access_pk PRIMARY KEY (id)
);

ALTER TABLE access ADD CONSTRAINT access_foo
    FOREIGN KEY (foo_id)
    REFERENCES foo (id)
    ON DELETE  CASCADE 
    ON UPDATE  CASCADE 
    DEFERRABLE 
    INITIALLY DEFERRED;

在我的代码中,我首先声明: client.query('BEGIN');(我正在使用npm库“ pg”) 在表'foo'中插入一行,然后在第一个插入中插入另一个具有foo_id的'access'插入。之后是client.query('COMMIT');

所有这些操作都在try捕获中,并且在捕获中为client.query('ROLLBACK');,并且如果其中一个插入都存在问题,则回滚似乎可以正常进行。当一切都应该提交后,我仍然会在catch块中结束该操作:

消息:“在表“ access”上插入或更新违反了外键约束“ access_foo””

详细信息:“表(foo)中不存在键(foo_id)=(20)。”

我认为延迟约束足以做到这一点,但是我想我错了。欢迎任何帮助。

1 个答案:

答案 0 :(得分:1)

您可能对事务划分有一些问题。我进行了一个简单的测试,效果很好。

insert into foo (id, foo) values (1, 'Anne');

start transaction;

insert into access (id, foo_id) values (101, 1);

insert into access (id, foo_id) values (107, 7); -- 7 does not exist yet...

insert into foo (id, foo) values (7, 'Ivan'); -- 7 now exists!

commit; -- at this point all is good

请参见DB Fiddle上的运行示例。