我遇到了sqlite3和SQLAlchemy的问题,我的外键是使用带有ondelete =" RESTRICT"的ForeignKey创建的,并且每个会话执行" PRAGMA foreign_keys = on&# 34;,但SQLAlchemy仍允许我孤儿。试图在sqlite3本身中删除相同的行会引发外键错误。
这是我的SQLAlchemy模型:
class User(Base):
__tablename__ = 'users'
username = Column(String, nullable=False, unique=True, primary_key=True)
account_type = Column(String, ForeignKey("account_types.name", ondelete="RESTRICT"), nullable=False)
class AccountType(Base):
__tablename__ = 'account_types'
name = Column(String, nullable=False, unique=True, primary_key=True)
description = Column(String)
现在,我打开与数据库的连接并执行以下操作:
engine = create_engine("sqlite3:///mydatabase")
Session = sessionmaker(bind=engine)
session = Session()
session.execute("PRAGMA foreign_keys = on")
# This gives me the expected result:
# I can't add a user which references an account type I haven't
# created yet
new_user = User(username="abc123",
account_type="admin") # "admin" doesn't exist yet
session.add(new_user)
with pytest.raises(sqlalchemy.exc.IntegrityError):
session.commit()
session.rollback()
new_account_type = AccountType(name="admin",
description="blah blah blah")
session.add(new_account_type)
session.commit()
# Now add our new user (Horray, this now works!)
session.add(new_user)
session.commit()
# Now let's try to delete the account type
# This should raise an integrity error, but it doesn't!
# SELECT * FROM account_types and SELECT * FROM users
# show that the user still exists, but the account type doesn't
session.query(AccountType).filter_by(name="admin").delete()
session.commit()
现在,将SQLAlchemy排除在等式之外,清除表格,并手动插入/删除此数据,并且sqlite3正在遵循" ON DELETE RESTRICT":
sqlite> PRAGMA foreign_keys = on;
sqlite> DELETE FROM users;
sqlite> DELETE FROM account_types;
sqlite> .schema users
CREATE TABLE users (
username VARCHAR NOT NULL,
account_type VARCHAR NOT NULL,
PRIMARY KEY (username),
UNIQUE (username),
FOREIGN KEY(account_type) REFERENCES account_types (name) ON DELETE RESTRICT
);
sqlite> .schema account_types
CREATE TABLE account_types (
name VARCHAR NOT NULL,
description VARCHAR,
PRIMARY KEY (name),
UNIQUE (name)
);
sqlite> INSERT INTO account_types VALUES ("admin", "blah blah blah");
sqlite> INSERT INTO users VALUES ("abc123", "admin");
sqlite> DELETE FROM account_types WHERE name = "admin";
Error: FOREIGN KEY constraint failed
=============================================== ==
为什么SQLAlchemy(1.0.12)不会尊重" ON DELETE RESTRICT" sqlite3中的约束?
如果重要,表(和约束)都是通过SQLAlchemy生成的:
engine = create_engine("sqlite3:///mydatabase")
Base.metadata.create_all(engine)
答案 0 :(得分:1)
我在张贴前大约两个小时与此搏斗,然后在发布后大约一个小时,我想通了。这是任何其他孤独的SQLAlchemy新手的答案,他现在或几年后到达这个页面。 " session.rollback()"是"撤消"我之前执行的" PRAGMA foreign_keys = on"。
我从之前的一些内部源代码中提取了设置会话的方法,所以我认为没关系。该手册确切地说明了如何在http://docs.sqlalchemy.org/en/latest/dialects/sqlite.html#foreign-key-support
处理这个问题简而言之,我补充道:
element1:target ~ element2 {//does something}
到我的模块,其中包含我的所有模型,它只是"工作"。不需要以任何方式调用此方法。现在我的外键约束总是被尊重,甚至是后滚回。