Обновите схему базы данных sqlite с sqlalchemy и elixir

Я создал приложение python, которое использует elixir/sqlalchemy для хранения данных. Второй выпуск программного обеспечения требует обновления любых файлов, созданных в предыдущей версии, для добавления/удаления таблиц и столбцов.

Мой вопрос: как я могу это достичь? Я знаю sqlalchemy-migrate, но должен сказать, что я нахожу это запутанным. В нем не упоминается, что происходит с существующими данными. Более того, sqlite уменьшил поддержку ALTER TABLE, так что будет мигрировать, если я попытаюсь удалить столбец? Существуют ли какие-либо другие способы использования миграции?

Ответ 1

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

Многие фреймворки, такие как Django или Ruby on Rails, имеют встроенную или доступную систему миграции в качестве подключаемого модуля. В вашем случае с SQLAlchemy есть несколько вариантов:

  • Не используйте какую-либо систему. Просто напишите /tmp/migrate.sql руками, запишите инструкции ALTER/DROP/CREATE, переместите пальцы и примените их к базе SQLite. Это, как правило, плохая идея, поскольку она подвержена ошибкам, но выбор зависит от вас. Отсутствие полнофункционального оператора ALTER TABLE можно было бы обработать, создав новый столбец с требуемыми свойствами с временным именем, скопировав все данные из исходного столбца на него, удалив исходный столбец и переименовав новый столбец в исходное имя. Такой же метод можно использовать на уровне таблицы.
  • Используйте некоторую стороннюю миграционную систему, такую ​​как liquibase. Liquibase классная, хорошо спроектированная и мощная, за исключением одного недостатка. Это действительно багги. Я попробовал это для SQLite (и да для SQLAlchemy, но на самом деле это неважно), и он не смог выполнить некоторые довольно простые вещи. Я googled для проблем и обнаружил, что они известные ошибки.
  • Использовать SQLAlchemy-migrate, о которой вы упоминали. Он не так силен, как ROR-миграции, на которые он был вдохновлен, ни он не столь же мощный, как ликбаза, но он работает. Ограничение SQLite можно было бы работать одинаково.

И вы спросили, что сделает SQLAlchemy-migrate, если вы попытаетесь удалить столбец. Ну, он удалит столбец и поэтому удалит все данные, которые были в нем. Остальные столбцы в таблице будут сохранены.

Ответ 2

Более поздняя альтернатива sqlalchemy-migrate - alembic, написанная автором SQLAlchemy сам. Хотя последний ( "тот же автор" ) выглядит сильным аргументом, недостатком может быть то, что он не поддерживает таблицу ALTERation с помощью SQLite, то есть у нее нет встроенных обходных путей для поддержки SQLite без поддержки ALTER. (Можно было бы утверждать, что это выходит за рамки и вполне может быть решено с помощью специализированного пакета python или расширения SQLite.)

Ответ 3

Что вас смущает в sqlalchemy-migrate? Он имеет параметры --preview_sql и --preview_py для предварительного просмотра того, что он собирается делать. В общем случае невозможно выполнить правильную миграцию для любого возможного случая, но вы можете изменить сгенерированную миграцию script для удовлетворения ваших потребностей. Легко получить ответы на остальные, попробовав его.