Добавить столбец в таблицу SQLAlchemy
Я сделал таблицу с использованием SQLAlchemy и забыл добавить столбец. Я в основном хочу сделать это:
users.addColumn('user_id', ForeignKey('users.user_id'))
Какой синтаксис для этого? Я не мог найти это в документах.
13 ответов
Это называется миграцией базы данных (SQLAlchemy не поддерживает миграцию из коробки). Вы можете посмотреть на использование sqlalchemy-migrate, чтобы помочь в подобных ситуациях, или вы можете просто ALTER TABLE
через утилиту командной строки выбранной вами базы данных,
У меня та же проблема, и мысль об использовании библиотеки миграции только для этой тривиальной вещи заставляет меня
дрожать. В любом случае, это моя попытка:
def add_column(engine, table_name, column):
column_name = column.compile(dialect=engine.dialect)
column_type = column.type.compile(engine.dialect)
engine.execute('ALTER TABLE %s ADD COLUMN %s %s' % (table_name, column_name, column_type))
column = Column('new column', String(100), primary_key=True)
add_column(engine, table_name, column)
Тем не менее, я не знаю, как вставить primary_key=True
в сырой запрос SQL.
См. Этот раздел документации по SQLAlchemy: http://docs.sqlalchemy.org/en/latest/core/metadata.html
Alembic является новейшим программным обеспечением, предлагающим этот тип функциональности, и разработано тем же автором, что и SQLAlchemy.
У меня есть база данных с именем "ncaaf.db", созданная с помощью sqlite3, и таблица с именем "игры". Так что я бы CD в тот же каталог в моей командной строке Linux и сделать
sqlite3 ncaaf.db
alter table games add column q4 type float
и это все, что нужно! Просто убедитесь, что вы обновляете свои определения в коде sqlalchemy.
from sqlalchemy import create_engine
engine = create_engine('sqlite:///db.sqlite3')
engine.execute('alter table table_name add column column_name String')
У меня была такая же проблема, я просто написал свою собственную функцию в raw sql. Если вы используете SQLITE3, это может быть полезно.
Затем, если вы добавите столбец к определению вашего класса в одно и то же время, похоже, все получится.
import sqlite3
def add_column(database_name, table_name, column_name, data_type):
connection = sqlite3.connect(database_name)
cursor = connection.cursor()
if data_type == "Integer":
data_type_formatted = "INTEGER"
elif data_type == "String":
data_type_formatted = "VARCHAR(100)"
base_command = ("ALTER TABLE '{table_name}' ADD column '{column_name}' '{data_type}'")
sql_command = base_command.format(table_name=table_name, column_name=column_name, data_type=data_type_formatted)
cursor.execute(sql_command)
connection.commit()
connection.close()
Да, вы можете установить sqlalchemy-migrate (pip install sqlalchemy-migrate) и использовать его в своем скрипте для вызова метода Table и Column create ():
from sqlalchemy import String, MetaData, create_engine
from migrate.versioning.schema import Table, Column
db_engine = create_engine(app.config.get('SQLALCHEMY_DATABASE_URI'))
db_meta = MetaData(bind=db_engine)
table = Table('tabel_name' , db_meta)
col = Column('new_column_name', String(20), default='foo')
col.create(table)
Просто продолжая простой путь, предложенный chasmani, небольшое улучшение
'''
# simple migration
# columns to add:
# last_status_change = Column(BigInteger, default=None)
# last_complete_phase = Column(String, default=None)
# complete_percentage = Column(DECIMAL, default=0.0)
'''
import sqlite3
from config import APP_STATUS_DB
from sqlalchemy import types
def add_column(database_name: str, table_name: str, column_name: str, data_type: types, default=None):
ret = False
if default is not None:
try:
float(default)
ddl = ("ALTER TABLE '{table_name}' ADD column '{column_name}' '{data_type}' DEFAULT {default}")
except:
ddl = ("ALTER TABLE '{table_name}' ADD column '{column_name}' '{data_type}' DEFAULT '{default}'")
else:
ddl = ("ALTER TABLE '{table_name}' ADD column '{column_name}' '{data_type}'")
sql_command = ddl.format(table_name=table_name, column_name=column_name, data_type=data_type.__name__,
default=default)
try:
connection = sqlite3.connect(database_name)
cursor = connection.cursor()
cursor.execute(sql_command)
connection.commit()
connection.close()
ret = True
except Exception as e:
print(e)
ret = False
return ret
add_column(APP_STATUS_DB, 'procedures', 'last_status_change', types.BigInteger)
add_column(APP_STATUS_DB, 'procedures', 'last_complete_phase', types.String)
add_column(APP_STATUS_DB, 'procedures', 'complete_percentage', types.DECIMAL, 0.0)
При использовании докера:
- перейдите к терминалу контейнера, содержащего вашу БД
- попасть в БД:
psql -U usr [YOUR_DB_NAME]
- теперь вы можете изменять таблицы, используя необработанный SQL:
alter table [TABLE_NAME] add column [COLUMN_NAME] [TYPE]
Обратите внимание, что вам нужно будет смонтировать свою БД, чтобы изменения сохранялись между сборками.
У меня недавно была такая же проблема, поэтому я высказал мнение AlexP в более раннем ответе. Проблема заключалась в том, чтобы добавить новый столбец в метаданные моей программы. Использование функции sqlAlchemy append_column имело некоторые неожиданные последующие эффекты ( объект 'str' не имеет атрибута 'dialect impl'). Я исправил это, добавив столбец с DDL (в данном случае база данных MySQL), а затем отразив таблицу обратно из БД в мои метаданные.
Код выглядит примерно следующим образом (немного изменен по сравнению с тем, что у меня есть, чтобы свести его к его минимальной сути. Прошу прощения за любые ошибки - если они есть, они должны быть незначительными)...
try:
# Use back quotes as a protection against SQL Injection Attacks. Can we do more?
common.qry_engine.execute('ALTER TABLE %s ADD COLUMN %s %s' %
('`' + self.tbl.schema + '`.`' + self.tbl.name + '`',
'`' + self.outputs[new_col] + '`', 'VARCHAR(50)'))
except exc.SQLAlchemyError as msg:
raise GRError(desc='Unable to physically add derived column to table. Contact support.',
data=str(self.outputs), other_info=str(msg))
try: # Refresh the metadata to show the new column
self.tbl = sqlalchemy.Table(self.tbl.name, self.tbl.metadata, extend_existing=True, autoload=True)
except exc.SQLAlchemyError as msg:
raise GRError(desc='Unable to establish metadata for new column. Contact support.',
data=str(self.outputs), other_info=str(msg))
Вы можете использовать SQLite Studio для создания новых столбцов в существующих таблицах. Загрузите форму SQLite studio здесь: https://sqlitestudio.pl/
Добавление столбца "вручную" (без использования python или SQLAlchemy), пожалуй, самое простое?
Та же проблема здесь. Что я сделаю, так это перебираю базу данных и добавляю каждую запись в новую базу данных с дополнительным столбцом, затем удаляю старую базу данных и переименовываю новую в эту.