sqlite3" ON DELETE RESTRICT"通过SQLAlchemy不被尊重,但在sqlite3中工作正常

时间:2016-05-04 17:24:14

标签: python python-3.x sqlite sqlalchemy

我遇到了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)

1 个答案:

答案 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}

到我的模块,其中包含我的所有模型,它只是"工作"。不需要以任何方式调用此方法。现在我的外键约束总是被尊重,甚至是后滚回。