Sqlite / SQLAlchemy: как осуществить Внешние ключи?

Новая версия SQLite имеет способность осуществить ограничения Внешнего ключа, но ради назад-совместимости, необходимо включить его для каждого соединения с базой данных отдельно!

sqlite> PRAGMA foreign_keys = ON;

Я использую SQLAlchemy - как я могу удостовериться, что это всегда включается? То, что я попробовал, является этим:

engine = sqlalchemy.create_engine('sqlite:///:memory:', echo=True)
engine.execute('pragma foreign_keys=on')

... но это не работает!... Что я пропускаю?

Править: Я думаю, что моя настоящая проблема состоит в том, что у меня есть больше чем одна версия SQLite, установленного, и Python не использует последний!

>>> import sqlite3
>>> print sqlite3.sqlite_version
3.3.4

Но я просто загрузил 3.6.23 и поместил exe в свой каталог проекта! Как я могу выяснить, какой .exe это использует, и измените его?

32
задан Nick Perkins 13 April 2010 в 22:48
поделиться

3 ответа

Теперь у меня работает следующее:

Скачайте последние сборки 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

Затем добавьте 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()])

Затем будьте осторожны, как вы проверяете, работают ли внешние ключи: Здесь у меня возникла некоторая путаница. Когда я использовал sqlalchemy ORM для add() вещей, мой код импорта неявно обрабатывал подключаемые отношения, поэтому никогда не мог потерпеть неудачу. Добавление nullable=False в некоторые ForeignKey() утверждения помогло мне здесь.

Способ, которым я проверяю, включена ли поддержка внешних ключей 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) 

Здесь wall_id и type_id являются ForeignKey() и sqlite теперь корректно выбрасывает исключение при попытке подцепить недействительные fkeys. Так что все работает! Если вы удалите слушателя, то sqlalchemy будет радостно добавлять недействительные записи.

Я думаю, что основной проблемой может быть несколько sqlite3.dll (или .so), лежащих вокруг.

15
ответ дан 27 November 2019 в 19:51
поделиться

У меня была такая же проблема раньше (скрипты с ограничениями внешних ключей выполнялись, но текущие ограничения не выполнялись движком sqlite); удалось ее решить:

  1. загрузив, построив и установив последнюю версию sqlite отсюда: sqlite-sqlite-amalgamation ; до этого у меня на машине с Ubuntu был sqlite 3.6.16; который еще не поддерживал внешние ключи; он должен быть 3.6.19 или выше, чтобы они работали.

  2. установка последней версии pysqlite отсюда: pysqlite-2.6.0

после этого я начал получать исключения всякий раз, когда ограничение внешнего ключа не удалось

надеюсь, что это поможет, касательно

3
ответ дан 27 November 2019 в 19:51
поделиться

Если вам нужно выполнить что-то для настройки при каждом подключении, используйте PoolListener .

2
ответ дан 27 November 2019 в 19:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: