我正在尝试将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)。”
我认为延迟约束足以做到这一点,但是我想我错了。欢迎任何帮助。
答案 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上的运行示例。