【发布时间】:2021-06-24 12:39:54
【问题描述】:
我正在尝试将数据插入两个表中,后者引用前者。比如:
CREATE TABLE foo (foo_id bigserial primary key, name varchar)
CREATE TABLE bar (bar_id bigserial primary key, name varchar,
foo_id int constraint foo_fkey references foo)
我想在一个事务中添加两行,这样如果出现任何故障,就不会向数据库写入任何内容。如果我只是将两个对象都添加到我的会话中,我不会得到自动递增的 foo_id,所以我添加 foo 对象,执行刷新(填充 id),然后设置 bar 对象,然后再次刷新(我以后还有更多工作要做,但没有被这种关系引用。在第二次刷新时,我收到了一个引用完整性错误,因为 foo 中的行实际上并没有被写入。
我可以在 SQL 中轻松完成此操作:
BEGIN TRANSACTION;
INSERT INTO foo (name) values('foo');
INSERT INTO bar (name, foo_id) VALUES('bar', currval(pg_get_serial_sequence('foo', 'foo_id')));
COMMIT TRANSACTION;
有没有办法让我暂时暂停 RI 检查?或者,我有没有更好的方法来获取新的 foo_id 而不是刷新?
这是我正在执行的那种 sqla 代码:
session.begin()
f = Foo()
f.name = 'Foo'
session.add(f)
session.flush()
b = Bar()
b.name = 'Bar'
b.foo_id = f.foo_id
session.add(b)
session.flush()
...
session.commit()
session.close()
我稍后使用 bar_id 值,这就是我需要第二次刷新的原因。错误发生在第二次刷新时。
【问题讨论】:
-
你能分享示例 SQLA 代码吗?如果存在关系,您通常可以执行类似 `parent = Parent(child=child)` 之类的操作,并让键在提交时进行排序,而无需中间刷新。或者您可以使 FK 约束可延迟(我从未尝试过)。
-
@snakecharmerb,编辑了原始帖子以添加我正在执行的代码类型。实际的表/对象有更多的列,所以为了简洁起见,我在这里解释一下。我会看看我是否可以建立关系,看看是否有帮助......
-
好吧,我尝试使用关系,但我没有收到 RI 错误,但现在我也没有得到填充的 ID。没有刷新或提交。
标签: postgresql sqlalchemy referential-integrity