Sqlite / SQLAlchemy: как применять внешние ключи?

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

sqlite> PRAGMA foreign_keys = ON; 

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

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

… но это не работает! … Что мне не хватает?

EDIT: Я считаю, что моя реальная проблема заключается в том, что у меня установлена ​​более одной версии SQLite, а Python не использует последнюю версию!

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

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

7 Solutions collect form web for “Sqlite / SQLAlchemy: как применять внешние ключи?”

Теперь у меня это работает:

Загрузите последние сборки 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()]) 

Затем будьте осторожны, как вы проверяете, работают ли внешние ключи: у меня была некоторая путаница. При использовании ORM sqlalchemy для добавления () вещей мой код импорта неявно обрабатывал привязки отношений, поэтому никогда не мог потерпеть неудачу. Добавление '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), лежащих вокруг.

Для последних версий (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) 

Основываясь на ответах от conny и shadowmatter, вот код, который будет проверять, используете ли вы SQLite3 перед выпуском инструкции PRAGMA:

 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() 

На диалектной странице SQLite :

SQLite поддерживает синтаксис FOREIGN KEY при испускании операторов CREATE для таблиц, однако по умолчанию эти ограничения не влияют на работу таблицы.

Проверка ограничений на SQLite имеет три предварительных условия:

  • Должна быть использована хотя бы версия 3.6.19 SQLite
  • Библиотека SQLite должна быть скомпилирована без использования символов SQLITE_OMIT_FOREIGN_KEY или SQLITE_OMIT_TRIGGER.
  • Инструкция 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() 

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

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

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

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

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

В качестве более простого подхода, если ваше создание сеанса централизовано за вспомогательной функцией Python (а не непосредственно с помощью механизма SQLA), вы можете просто выдать «session.execute (« pragma foreign_keys = on ») перед возвратом только что созданного сеанса.

Вам нужен только подход слушателя пула, если произвольные части вашего приложения могут создавать сеансы SQLA против базы данных.

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

  • выберите из таблицы sqlite, где rowid в списке используется python sqlite3 - DB-API 2.0
  • Как читать datetime обратно из sqlite как datetime вместо строки в Python?
  • Как преобразовать десятичное число Python в числовое число SQLite?
  • Как обеспечить пользовательскую функцию для python blaze с помощью sqlite-бэкэнд?
  • Массивы NumPy с SQLite
  • django error 'слишком много значений для распаковки'
  • вставлять в таблицу sqlite с уникальным столбцом
  • Есть ли библиотека Python, которая позволяет создавать пользовательские интерфейсы без написания большого количества кода?
  • Как я могу ссылаться на столбцы по их именам в python, вызывающем SQLite?
  • Python, SQLite3: курсор возвращает дубликаты, когда коммит вмешивается
  • Обновление SQLite3 на моей установке python
  •  
    Interesting Posts for Van-Lav
    Python - лучший язык программирования в мире.