【发布时间】:2020-06-10 00:33:55
【问题描述】:
我正在尝试将我的 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。之后有client.query('COMMIT');
所有这些都在 try catch 中,并且在 catch 中是 client.query('ROLLBACK'); 并且如果任一插入出现问题,回滚似乎正在工作。当所有事情都应该提交时,我仍然会为此进入 catch 块:
消息:“在表“access”上插入或更新违反了外键约束“access_foo””
详细信息:“表“foo”中不存在键 (foo_id)=(20)。”
我认为延迟约束就足以做到这一点,但我想我错了。欢迎任何帮助。
【问题讨论】:
-
PostgreSQL 中的
DEFERRABLE INITIALLY DEFERRED在事务结束时验证外键约束。我猜你的事务划分有问题。 -
在错误消息中实际上您需要了解的内容非常多:Key (foo_id)=(20) is not present in table "foo" 所以您要插入访问 foo_id=20 但在那里没有 id=20 的行。您的 INSERT INTO 费用很可能失败。
-
请注意,您不能
DELETE父记录,然后在提交之前重新插入它,当孩子存在时。我学得很辛苦。
标签: sql node.js postgresql