6

How does one add a UniqueConstraint which is Case Insensitive using SQLalchemy?

Ilja Everilä
  • 50,538
  • 7
  • 126
  • 127
John Mutuma
  • 3,150
  • 2
  • 18
  • 31

2 Answers2

7

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.

jspcal
  • 50,847
  • 7
  • 72
  • 76
3

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.

0buz
  • 3,443
  • 2
  • 8
  • 29
John Mutuma
  • 3,150
  • 2
  • 18
  • 31