具有现有主键约束的 alembic alter_column
alembic alter_column with existing primary key constraint
我需要用 alembic 改变列的类型。目前我的代码如下所示:
with op.batch_alter_table('annotations', schema=None) as batch_op:
batch_op.alter_column('anno_id', existing_type=sa.Integer(), type_=sa.String(36))
我的问题是 anno_id 是 table 的主键,虽然代码在 sqlite 上运行良好,但 MS SQL 拒绝命令:
The object 'PK__annotati__2CC37C988C804EF7' is dependent on column 'anno_id'.DB-Lib error message 20018, severity 16
PK 约束是自动生成的,所以我无法提前知道它的名称。我需要做什么来识别约束并在更改列后删除并重新创建它?
更新,根据 Aaron Bertrand 在下面的回答,我能够在 alembic 中执行以下操作。不幸的是,正如他所说,我无法直接更改列以将其更改为字符串类型,所以我 dropped/recreated 它。
if context.get_impl().bind.dialect.name == "mssql":
batch_op.execute("""
DECLARE @sql nvarchar(max) = N'',
@table nvarchar(513) = QUOTENAME(N'annotations'),
@column nvarchar(128) = QUOTENAME(N'anno_id');
SELECT @sql += N'ALTER TABLE dbo.'
+ @table + N' DROP CONSTRAINT '
+ QUOTENAME(name) + N';'
FROM sys.key_constraints
WHERE type = N'PK' AND parent_object_id = OBJECT_ID(N'dbo.' + @table);
EXEC sys.sp_executesql @sql;
""")
batch_op.drop_column('anno_id')
batch_op.add_column(sa.Column('anno_id', sa.String(36), nullable=False))
batch_op.create_primary_key('annotations_pkey', ['anno_id'])
The PK constraint was auto-generated so I can't know in advance what its name is
您可以随时更改它(并更改 生成 table 的任何代码,这样它就不会将这些名称留给数据库来分配)。
EXEC sys.sp_rename
N'PK__anno_3213E83F046D1D25', -- you'll have to look this up once
N'PK_annotations',
N'OBJECT';
如果您无法修复数据库中的这个设计缺陷,那么您可以在需要时查找它:
SELECT name FROM sys.key_constraints
WHERE type = N'PK'
AND parent_object_id = OBJECT_ID(N'dbo.annotations');
您可以使用它来生成 drop/create 命令,以便您可以更改任何受影响的列,但它需要一些额外的上下文(例如 PK 适用于哪些列)。一个例子可能是:
DECLARE @sql nvarchar(max) = N'',
@table nvarchar(513) = QUOTENAME(N'annotations'),
@column nvarchar(128) = QUOTENAME(N'anno_id');
SELECT @sql += N'ALTER TABLE dbo.'
+ @table + N' DROP CONSTRAINT '
+ QUOTENAME(name) + N';'
FROM sys.key_constraints
WHERE type = N'PK' AND parent_object_id = OBJECT_ID(N'dbo.' + @table);
SELECT @sql += char(13) + char(10) + N'ALTER TABLE dbo.'
+ @table + N' ALTER COLUMN '
+ @column + N' decimal(14,4) NOT NULL;'
FROM sys.key_constraints
WHERE type = N'PK'
AND parent_object_id = OBJECT_ID(N'dbo.' + @table);
SELECT @sql += char(13) + char(10) + N'ALTER TABLE dbo.'
+ @table
+ N' ADD CONSTRAINT PK_Annotations PRIMARY KEY(' + @column + N');';
PRINT @sql;
--EXEC sys.sp_executesql @sql;
这将像这样生成 SQL(您可以 PRINT
在注释掉 EXEC
之前验证)。
ALTER TABLE dbo.[annotations] DROP CONSTRAINT [PK__annotati__2CC37C98902B2CC2];
ALTER TABLE dbo.[annotations] ALTER COLUMN [anno_id] decimal(14,4) NOT NULL;
ALTER TABLE dbo.[annotations] ADD CONSTRAINT PK_Annotations PRIMARY KEY([anno_id]);
- db<>fiddle
上的工作示例
这是 运行 在像 SQL Server Management Studio 这样的工具中。我非常怀疑您是否能够 直接从 alembic 构建这样的东西; ORM 并不完全以处理所有用例而闻名,只是处理最低限度的用例。一旦您需要在最低限度范围之外做一些甚至远程的事情,您就需要离开 ORM。
这不会是结束。因为我假设即使您不尝试以 可能 使 SQL 服务器认为会丢失数据的方式更改列(例如更改 numeric(14,4) -> numeric(12,2)
),如果有指向它的外键、针对 table 的索引视图等,您也将无法删除 PK
我需要用 alembic 改变列的类型。目前我的代码如下所示:
with op.batch_alter_table('annotations', schema=None) as batch_op:
batch_op.alter_column('anno_id', existing_type=sa.Integer(), type_=sa.String(36))
我的问题是 anno_id 是 table 的主键,虽然代码在 sqlite 上运行良好,但 MS SQL 拒绝命令:
The object 'PK__annotati__2CC37C988C804EF7' is dependent on column 'anno_id'.DB-Lib error message 20018, severity 16
PK 约束是自动生成的,所以我无法提前知道它的名称。我需要做什么来识别约束并在更改列后删除并重新创建它?
更新,根据 Aaron Bertrand 在下面的回答,我能够在 alembic 中执行以下操作。不幸的是,正如他所说,我无法直接更改列以将其更改为字符串类型,所以我 dropped/recreated 它。
if context.get_impl().bind.dialect.name == "mssql":
batch_op.execute("""
DECLARE @sql nvarchar(max) = N'',
@table nvarchar(513) = QUOTENAME(N'annotations'),
@column nvarchar(128) = QUOTENAME(N'anno_id');
SELECT @sql += N'ALTER TABLE dbo.'
+ @table + N' DROP CONSTRAINT '
+ QUOTENAME(name) + N';'
FROM sys.key_constraints
WHERE type = N'PK' AND parent_object_id = OBJECT_ID(N'dbo.' + @table);
EXEC sys.sp_executesql @sql;
""")
batch_op.drop_column('anno_id')
batch_op.add_column(sa.Column('anno_id', sa.String(36), nullable=False))
batch_op.create_primary_key('annotations_pkey', ['anno_id'])
The PK constraint was auto-generated so I can't know in advance what its name is
您可以随时更改它(并更改 生成 table 的任何代码,这样它就不会将这些名称留给数据库来分配)。
EXEC sys.sp_rename
N'PK__anno_3213E83F046D1D25', -- you'll have to look this up once
N'PK_annotations',
N'OBJECT';
如果您无法修复数据库中的这个设计缺陷,那么您可以在需要时查找它:
SELECT name FROM sys.key_constraints
WHERE type = N'PK'
AND parent_object_id = OBJECT_ID(N'dbo.annotations');
您可以使用它来生成 drop/create 命令,以便您可以更改任何受影响的列,但它需要一些额外的上下文(例如 PK 适用于哪些列)。一个例子可能是:
DECLARE @sql nvarchar(max) = N'',
@table nvarchar(513) = QUOTENAME(N'annotations'),
@column nvarchar(128) = QUOTENAME(N'anno_id');
SELECT @sql += N'ALTER TABLE dbo.'
+ @table + N' DROP CONSTRAINT '
+ QUOTENAME(name) + N';'
FROM sys.key_constraints
WHERE type = N'PK' AND parent_object_id = OBJECT_ID(N'dbo.' + @table);
SELECT @sql += char(13) + char(10) + N'ALTER TABLE dbo.'
+ @table + N' ALTER COLUMN '
+ @column + N' decimal(14,4) NOT NULL;'
FROM sys.key_constraints
WHERE type = N'PK'
AND parent_object_id = OBJECT_ID(N'dbo.' + @table);
SELECT @sql += char(13) + char(10) + N'ALTER TABLE dbo.'
+ @table
+ N' ADD CONSTRAINT PK_Annotations PRIMARY KEY(' + @column + N');';
PRINT @sql;
--EXEC sys.sp_executesql @sql;
这将像这样生成 SQL(您可以 PRINT
在注释掉 EXEC
之前验证)。
ALTER TABLE dbo.[annotations] DROP CONSTRAINT [PK__annotati__2CC37C98902B2CC2];
ALTER TABLE dbo.[annotations] ALTER COLUMN [anno_id] decimal(14,4) NOT NULL;
ALTER TABLE dbo.[annotations] ADD CONSTRAINT PK_Annotations PRIMARY KEY([anno_id]);
- db<>fiddle 上的工作示例
这是 运行 在像 SQL Server Management Studio 这样的工具中。我非常怀疑您是否能够 直接从 alembic 构建这样的东西; ORM 并不完全以处理所有用例而闻名,只是处理最低限度的用例。一旦您需要在最低限度范围之外做一些甚至远程的事情,您就需要离开 ORM。
这不会是结束。因为我假设即使您不尝试以 可能 使 SQL 服务器认为会丢失数据的方式更改列(例如更改 numeric(14,4) -> numeric(12,2)
),如果有指向它的外键、针对 table 的索引视图等,您也将无法删除 PK