简体   繁体   English

使用 SQLAlchemy 和 MS SQL Server 实现 Unique if not Null 约束

[英]Implementing Unique if not Null Constraint with SQLAlchemy and MS SQL Server

I want to enforce a unique constraint on a column but only if it is not null.我想对列强制执行唯一约束,但前提是它不为空。 This is the default behavior in SQLite, but not in MS SQL Server.这是 SQLite 中的默认行为,但不是 MS SQL Server 中的默认行为。

It seems the way to accomplish this in SQL Server is to use an index with a where clause, as described in this post .这似乎在SQL Server中实现这一点的方法是使用一个索引与where子句,如在这个岗位 My question is how do I do that in SQLAlchemy and have it still work with SQLite.我的问题是我如何在 SQLAlchemy 中做到这一点并让它仍然与 SQLite 一起使用。

I think this is approximately what I want:我认为这大约是我想要的:

class MyClass(Base):
    __tablename__ = 'myclass'
    __table_args__ = (Index('unique_index', <where clause?>, unique=True)
    my_column = Column(Integer) # The column I want unique if not null

where <where clause?> is some expression that puts the index on my_column where it is not NULL . where <where clause?>是一些表达式,它将索引放在my_column ,它不是NULL It seems this is possible by reading the documentation for index, but I do not know what expression I would need.通过阅读索引文档,这似乎是可能的,但我不知道我需要什么表达式。 Help with this or a different approach would be much appreciated.对此或不同方法的帮助将不胜感激。

SQL Server solution using filtered index:使用过滤索引的SQL Server解决方案:

CREATE TABLE tab(col INT);
CREATE UNIQUE INDEX uq_tab_col ON tab(col) WHERE col IS NOT NULL;

INSERT INTO tab(col) VALUES (1),(2),(NULL),(NULL);

-- INSERT INTO tab(col) VALUES (1);
-- Cannot insert duplicate key row in object 'dbo.tab' with unique index 'uq_tab_col'.
-- The duplicate key value is (1).

SELECT * FROM tab;

LiveDemo

For anyone else that finds this later.对于后来发现这一点的任何其他人。 SQL Alchemy does now support this index documentation . SQL Alchemy 现在支持此索引文档

import sqlalchemy as sa

sa.Table(
    sa.Column('column', sa.String(50), nullable=True),
    sa.Index('uq_column_allows_nulls', mssql_where=sa.text('column IS NOT NULL'),
)

If you are planning on using alembic like I was use this code.如果您打算像我使用此代码一样使用 alembic。

import sqlalchemy as sa
import alembic as op

op.create_index(
    name='uq_column_name',
    table_name='table',
    columns=['column'],
    mssql_where=sa.text('column IS NOT NULL'),
)

This uses the sql expression text for sqlalchemy and create_index 's dialect_expression key word arguments mssql_where=这使用sqlalchemysql 表达式文本和create_indexdialect_expression 关键字参数mssql_where=

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM