Nic*_*ins 32 python sqlite sqlalchemy foreign-keys
新版本的SQLite能够强制执行外键约束,但为了向后兼容,您必须分别为每个数据库连接打开它!
sqlite> PRAGMA foreign_keys = ON;
Run Code Online (Sandbox Code Playgroud)
我正在使用SQLAlchemy - 我怎样才能确保它始终打开?我试过的是这个:
engine = sqlalchemy.create_engine('sqlite:///:memory:', echo=True)
engine.execute('pragma foreign_keys=on')
Run Code Online (Sandbox Code Playgroud)
......但它不起作用!...我错过了什么?
编辑: 我认为我的真正问题是我安装了多个版本的SQLite,并且Python没有使用最新的版本!
>>> import sqlite3
>>> print sqlite3.sqlite_version
3.3.4
Run Code Online (Sandbox Code Playgroud)
但我刚刚下载了3.6.23并将exe放在我的项目目录中!我怎样才能弄清楚它正在使用哪个.exe并进行更改?
con*_*nny 42
对于最新版本(SQLAlchemy~0.7),SQLAlchemy主页说:
不推荐使用PoolListener.请参阅PoolEvents.
然后CarlS的例子成为:
engine = create_engine(database_url)
def _fk_pragma_on_connect(dbapi_con, con_record):
dbapi_con.execute('pragma foreign_keys=ON')
from sqlalchemy import event
event.listen(engine, 'connect', _fk_pragma_on_connect)
Run Code Online (Sandbox Code Playgroud)
Kir*_*dda 31
基于conny和shadowmatter的答案,这里的代码将在发出PRAGMA语句之前检查您是否使用SQLite3:
from sqlalchemy import event
from sqlalchemy.engine import Engine
from sqlite3 import Connection as SQLite3Connection
@event.listens_for(Engine, "connect")
def _set_sqlite_pragma(dbapi_connection, connection_record):
if isinstance(dbapi_connection, SQLite3Connection):
cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA foreign_keys=ON;")
cursor.close()
Run Code Online (Sandbox Code Playgroud)
Car*_*rlS 15
我现在有这个工作:
如上所述下载最新的sqlite和pysqlite2版本:确保python在运行时使用正确的版本.
import sqlite3
import pysqlite2
print sqlite3.sqlite_version # should be 3.6.23.1
print pysqlite2.__path__ # eg C:\\Python26\\lib\\site-packages\\pysqlite2
Run Code Online (Sandbox Code Playgroud)
接下来添加一个PoolListener:
from sqlalchemy.interfaces import PoolListener
class ForeignKeysListener(PoolListener):
def connect(self, dbapi_con, con_record):
db_cursor = dbapi_con.execute('pragma foreign_keys=ON')
engine = create_engine(database_url, listeners=[ForeignKeysListener()])
Run Code Online (Sandbox Code Playgroud)
然后小心你如何测试外键是否正常工作:我在这里有些困惑.当使用sqlalchemy ORM添加()时,我的导入代码隐式处理关系连接,因此永远不会失败.在某些ForeignKey()语句中添加'nullable = False'对我有帮助.
我测试sqlalchemy sqlite外键支持的方法是从声明性ORM类中进行手动插入:
# example
ins = Coverage.__table__.insert().values(id = 99,
description = 'Wrong',
area = 42.0,
wall_id = 99, # invalid fkey id
type_id = 99) # invalid fkey_id
session.execute(ins)
Run Code Online (Sandbox Code Playgroud)
这里'wall_id'和'type_id'都是ForeignKey()和sqlite现在正确地抛出异常,如果尝试连接无效的fkeys.所以它有效!如果你删除了监听器,那么sqlalchemy将很乐意添加无效的条目.
我相信主要问题可能是多个sqlite3.dll(或.so)四处闲置.
sha*_*ter 10
SQLite在为表发出CREATE语句时支持FOREIGN KEY语法,但是默认情况下,这些约束对表的操作没有影响.
SQLite上的约束检查有三个先决条件:
- 至少必须使用版本3.6.19的SQLite
- 必须在未启用SQLITE_OMIT_FOREIGN_KEY或SQLITE_OMIT_TRIGGER符号的情况下编译SQLite库.
- 必须在使用前在所有连接上发出PRAGMA foreign_keys = ON语句.
SQLAlchemy允许通过使用事件自动为新连接发出PRAGMA语句:
from sqlalchemy.engine import Engine
from sqlalchemy import event
@event.listens_for(Engine, "connect")
def set_sqlite_pragma(dbapi_connection, connection_record):
cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA foreign_keys=ON")
cursor.close()
Run Code Online (Sandbox Code Playgroud)
康尼的答案的一句话版本:
from sqlalchemy import event
Run Code Online (Sandbox Code Playgroud)
event.listen(engine, 'connect', lambda c, _: c.execute('pragma foreign_keys=on'))
Run Code Online (Sandbox Code Playgroud)
作为一种更简单的方法,如果会话创建集中在Python帮助器函数的后面(而不是直接公开SQLA引擎),则只需发出 session.execute('pragma foreign_keys=on') before returning the freshly created session.
仅当应用程序的任意部分可能针对数据库创建SQLA会话时,才需要池侦听器方法。
| 归档时间: |
|
| 查看次数: |
13818 次 |
| 最近记录: |