How does one add a UniqueConstraint which is Case Insensitive using SQLalchemy?
In some databases, string columns are case-insensitive by default (MySQL, SQL Server), so you wouldn't need to do anything extra.
In others, you can create a functional index that enforces the case-insensitive unique constraint:
Index('myIndex', func.lower(mytable.c.myColumn), unique=True)
You can also specify a case-insensitive collation for the column if the database supports it. For instance SQLite has a 'NOCASE' collation:
myColumn = Column(String(255), collation='NOCASE', nullable=False)
See http://docs.sqlalchemy.org/en/latest/core/type_basics.html?highlight=collation#sqlalchemy.types.String.params.collation
You may also specify a user-defined type for your column if your database provides a suitable one. PostgreSQL has a citext data type which is case-insensitive. See https://github.com/mahmoudimus/sqlalchemy-citext
Finally you can customize the DDL to create the constraint for your specific database.
To add upon @jspcal's answer, if the model is defined using a class
, then one you would have to either instantiate it independently after declaring the model
or use the text
construct.
i.e.
from sqlalchemy.sql.expressions import func
class User(Base):
__tablename__ = 'user'
username = Column('username', String(24), nullable=False)
Index('user_username_index', func.lower(User.username), unique=True)
using the text construct:
from sqlalchemy.sql.expressions import text
class User(Base):
__tablename__ = 'user'
__table_args__ = (
Index('ix_user_name', text('LOWER(username)')),
)
username = Column('username', String(24), nullable=False)
NB: table_args needs to be a tuple or dict, hence the need for that trailing comma inside the parenthesis.
That will create an index on username
column of table user
in lowercase form. Therefore, data stored in this column is unique and case insensitive.