Alembic MSSQL 唯一约束允许空值

时间:2021-02-04 18:09:33

标签: sql-server python-3.x sqlalchemy alembic

要解决的问题

使用 MSSQL 我想要一个唯一且接受空值的列。

问题

  1. 将两行数据添加到允许空值的列中,如下面的实现中的唯一约束会给出以下错误:

    Violation of UNIQUE KEY constraint 'UQ_...'. Cannot insert duplicate key in 
    object 'TABLE'. The duplicate key value is (<NULL>). (2627) (SQLExecDirectW)"
    
  2. 降级列会导致与 reference 列相关的约束问题。约束会自动唯一命名,因此以编程方式删除很麻烦。

当前实施

alembic 操作是:

from alembic import op
import sqlalchemy as sa

#...

def upgrade():
    op.add_column(
        'TABLE', sa.Column('reference', sa.Integer(), nullable=True, unique=True),
    )


def downgrade():
    op.drop_column('TABLE', 'reference')

1 个答案:

答案 0 :(得分:0)

在唯一字段中允许空值的解决方案是:

  1. 定义列时不要创建唯一约束
op.add_column(
        'TABLE', sa.Column('reference', sa.Integer(), nullable=True), # No unique=True
    )
  1. 手动创建一个 unique index
op.create_index(
    'uq_reference_allow_nulls', table_name='TABLE', columns=['reference'],
    mssql_where=sa.text('reference IS NOT NULL'), unique=True,
)
  1. 降级时删除索引。
op.drop_index('uq_reference_allow_nulls', table_name='TABLE')

这也解决了由于删除了 unique 参数而对表具有随机唯一约束的问题。总的来说,alembic 修订版如下所示:

from alembic import op
import sqlalchemy as sa

#...

def upgrade():
    op.add_column(
        'TABLE', sa.Column('reference', sa.Integer(), nullable=True),  # Do not include unique here
    )
    op.create_index(
        'uq_reference_allow_nulls', table_name='TABLE', columns=['reference'],
        mssql_where=sa.text('reference IS NOT NULL'), unique=True,
    )


def downgrade():
    op.drop_index('uq_reference_allow_nulls', table_name='TABLE')
    op.drop_column('TABLE', 'reference')

相关问题