我正在使用 SQLAlchemy-Migrate 来管理我的 PostgreSQL 数据库的迁移。我更改了模型的
__tablename__
,运行迁移更改了数据库中的名称,但表中的所有行都被删除了。如何在不删除数据的情况下重命名模型?
class Contract(db.Model):
__tablename__ = 'contract'
id = db.Column(db.Integer, primary_key=True)
is_valid = db.Column(db.Boolean, default=IS_VALID)
我将它从
contract
重命名为 contracts
并进行迁移:
def upgrade(migrate_engine):
pre_meta.bind = migrate_engine
post_meta.bind = migrate_engine
pre_meta.tables['contract'].drop()
post_meta.tables['contracts'].create()
它删除旧表并创建一个新表。我从未检查过其他迁移脚本,因为它们总是在不丢失数据的情况下运行。
SQLAlchemy-Migrate 不知道数据库中名为“contract”的表与代码中名为“contracts”的模型相同。它们是不同的名称,它只是做一个简单的比较。这就是为什么您 always 检查生成的迁移脚本以确保它们做正确的事情。
rename
方法重命名表。
pre_meta.tables['contract'].rename('contracts')
如果您使用的是 Alembic(或 Flask-Alembic,或 Flask-Migrate)而不是 SQLAlchemy-Migrate,同样的事情也会发生。使用
rename_table
方法。
op.rename_table('contract', 'contracts')
我在使用时遇到了类似的问题
op.rename_table("old_name", "new_name")
我不断得到
psycopg2.errors.DuplicateTable:关系“new_name”已经存在
最后,我用了
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
# op.drop_table('uploaded_resource')
op.drop_table('sessions')
op.execute('DROP TABLE IF EXISTS new_name')
op.execute('ALTER TABLE old_name RENAME TO new_name')
op.execute('ALTER SEQUENCE old_name_id_seq RENAME TO new_name_id_seq')
op.execute('ALTER INDEX old_name_pkey RENAME TO new_name_pkey')
....
和
def downgrade():
...
op.execute('ALTER TABLE new_name RENAME TO old_name')
op.execute('ALTER SEQUENCE new_name_id_seq RENAME TO old_name_id_seq')
op.execute('ALTER INDEX new_name_pkey RENAME TO old_name_pkey')
这不太理想。
这也有一定帮助 https://petegraham.co.uk/rename-postgres-table-with-alembic/
只是添加到@davidism的答案中,在使用
op.rename_table()
功能时,您应该确保也添加相关的降级代码。
例如: 如果您的
op.renam_table('table_name', 'new_table_name')
函数中有 upgrade()
,那么您需要在 op.rename_table('new_table_name', 'table_name')
函数中包含 downgrade()
,以防出现任何问题。
希望这对看到这个的人有所帮助,因为这已经是一个老问题了。