我正在使用SQLAlchemy和PostgreSQL。 Postgres支持执行延迟约束,这允许我们推迟检查表上的约束,直到事务结束。
例如,在SQLAlchemy中,我可能会定义一个这样的表:
t_group_categories = Table('group_categories', metadata,
Column('id', Integer, primary_key=True),
Column('group_id', Integer, ForeignKey('groups.id', deferrable=True))
)
SQLAlchemy会生成一个CREATE TABLE
语句,如下所示:
CREATE TABLE group_categories
(
id serial NOT NULL,
group_id integer,
CONSTRAINT group_categories_pkey PRIMARY KEY (id),
CONSTRAINT group_categories_group_id_fkey FOREIGN KEY (group_id)
REFERENCES groups (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE DEFERRABLE INITIALLY IMMEDIATE
)
据我了解,DEFERRABLE INITIALLY IMMEDIATE
表示FOREIGN KEY
约束
将被视为不可延迟的约束,除非明确告知
否则,这正是我想要的。
问题是我似乎无法找到有关如何让SQLAlchemy核心在事务内部实际发出SET CONSTRAINTS ... DEFERRED
命令的任何信息。
例如,假设我有以下代码:
connection = engine.connect()
...
with connection.begin() as transaction:
# Create a group
r = connection.execute(
t_groups.insert().values(...)
)
group_id = r.inserted_primary_key
# Assign a category to the group (ERROR!)
r2 = connection.execute(
t_group_categories.insert().values(group_id=group_id, ...)
)
第一个块只是创建一个新组。然后第二个块尝试分配该组
我们刚创建了一个类别。问题是如果没有特殊的SET CONSTRAINTS ... DEFERRED
,
我们实际上无法在不违反外键约束的情况下创建group_categories
条目
在桌子上,因为交易尚未提交。
在这个实例中我想做的是推迟检查约束,直到事务提交为止。 如何在事务完成之前实际推迟约束检查?
注意:
DEFERRABLE INITIALLY DEFERRED
感兴趣,我不愿意这样做。相反(如果可能的话),我希望将约束保持为DEFERRABLE INITIALLY IMMEDIATE
并明确标记需要延迟约束的实例。 DEFERRABLE INITIALLY DEFERRED
约束的那个,所以我希望/假设它有一种表达方式在另一边实际使用这个约束(即表达语言方式发出{{1 }}。更新
SET CONSTRAINTS ... DEFERRED
似乎也没有任何效果;我仍然遇到IntegrityError。connection.execute("SET CONSTRAINTS ALL DEFERRED")
也会返回IntegrityError。答案 0 :(得分:1)
如this question中所述,外键约束can't be deferred,即使它们被声明为:
即使约束被宣布为可延迟,也不能推迟除NO ACTION检查以外的参考动作。