我想通过 alembic 更改我的 PostgreSQL 数据库中字符串列的大小。
我在本地数据库中的第一次尝试是更直接的方式,也是一种看起来合乎逻辑的方式:
更改我想要调整大小的 db.Column 字段的大小并配置 alembic 以查找类型更改,如此处所述:将compare_type=True
参数添加到context.configure()
my alembic/env.py
. 然后运行alembic revision --autogenerate
其中正确生成的文件调用alter_column
.
这似乎没问题,但是alembic upgrade head
由于我取消了执行并寻找其他解决方案的 alter 列而花费了很多时间,因为我猜如果在我的计算机中花费这么长时间,那么在 Heroku 服务器中也会花费很长时间,我在此操作完成之前,我不会暂停我的服务。
所以我想出了一个在我的机器上完美运行的非常hacky的解决方案:
我在一个用于升级和降级的 alembic 文件中创建了我的更新语句:
connection = op.get_bind()
def upgrade():
connection.execute("update pg_attribute SET atttypmod = 1000+4" + \
"where attrelid = 'item'::regclass and attname = 'details'", execution_options=None)
def downgrade():
connection.execute("update pg_attribute SET atttypmod = 200+4" + \
"where attrelid = 'item'::regclass and attname = 'details'", execution_options=None)
在我的机器上工作得非常快。但是当将它推送到我在 Heroku 中的暂存应用程序并执行升级时,它会提示ERROR: permission denied for relation pg_attribute
。如果我尝试直接在 psql 中执行更新语句,也会发生同样的情况。我想这是 Heroku 故意的,我不应该更新这类表,因为如果做错了可能会使数据库出现故障。我猜想在 Heroku 中强制更新不是要走的路。
我还尝试创建一个新的临时列,将旧小列中的所有数据复制到该临时列中,删除旧列,创建一个与旧列同名但具有所需大小的新列,复制临时列中的数据并以这种方式将其删除:
def upgrade():
op.add_column('item', sa.Column('temp_col', sa.String(200)))
connection.execute("update item SET temp_col = details", execution_options=None)
op.drop_column('item', 'details')
op.add_column('item', sa.Column('details', sa.String(1000)))
connection.execute("update item SET details = temp_col", execution_options=None)
op.drop_column('item', 'temp_col')
def downgrade():
op.add_column('item', sa.Column('temp_col', sa.String(1000)))
connection.execute("update item SET temp_col = details", execution_options=None)
op.drop_column('item', 'details')
op.add_column('item', sa.Column('details', sa.String(200)))
connection.execute("update item SET details = temp_col", execution_options=None)
op.drop_column('item', 'temp_col')
但这也需要很长时间,而且似乎不是一个真正整洁的方法。
所以我的问题是:在 Heroku 中通过 alembic 调整 postgreSQL 中的字符串列大小的正确方法是什么,而无需等待执行 alter 列的时间?