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 .

  • Зашифрованный файл или db в python
  • Python Почему не пишет контекстный менеджер для работы курсора sqlite3?
  • Почему я получаю ошибку 500 при попытке подключиться к базе данных sqlite?
  • Python SQLite: база данных заблокирована
  • Зачем закрывать курсор для Sqlite3 в Python
  • Обработать новый символ строки «\ n» в базе данных Sqlite с помощью Python?
  • Нет автоинкремента для Integer Первичный ключ в sqlite3
  • Выполнение скрипирования по сценарию, не включающему конвейер
  •  
    Interesting Posts for Van-Lav

    Передача столбцов в строки на python pandas

    Эффективный способ чтения определенного номера строки файла. (БОНУС: Pizon Manual Misprint)

    Преобразование столбца float в Spark Dataframe в VectorUDT

    Python Как просто перенаправить вывод печати в файл TXT с новой строкой, созданной для каждого перенаправления

    Как сбрасывать словарь Python в JSON, когда ключи являются нетривиальными объектами?

    ошибка индексации в списке в python

    как правильно перегрузить метод __add__ в python

    Как предотвратить блокирование блока кода с помощью KeyboardInterrupt в Python?

    Вывести дочерний тип с Django MTI или указать тип как поле?

    Возможно ли технически сделать скриншот веб-сайта программным путем?

    Итерация над двумерным списком питонов

    OpenCV Python: иногда возникает ошибка сегментации при использовании FlannBasedMatcher

    Изображения Keras CNN и размер ядра не совпадают даже после преобразования изображения в соответствии с

    Как загрузить файл через http с авторизацией в python 3.0, работая с ошибками?

    Передача набора массивов NumPy в функцию C для ввода и вывода

    Python - лучший язык программирования в мире.