SQLAlchemy中不区分大小写的字符串列?

13 投票
3 回答
8587 浏览
提问于 2025-04-15 21:51

我可以在sqlalchemy中创建一个不区分大小写的字符串列吗?我正在使用sqlite,可能通过数据库更改排序规则可以做到这一点,但我想在sqlalchemy/python中保持这个设置。

3 个回答

5

SQLAlchemy 默认情况下似乎不允许在创建表的时候使用 COLLATE 子句,但我终于找到了一种方法,可以在 SQLAlchemy 0.6 及以上版本中实现这个功能。不幸的是,这需要一些子类化和装饰器的使用,不过整体上还是比较简洁的。

from sqlalchemy import *
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.types import TypeDecorator

class CI_String(TypeDecorator): 
  """ Case-insensitive String subclass definition"""
  impl = String 
  def __init__(self, length, **kwargs):
      if kwargs.get('collate'):
          if kwargs['collate'].upper() not in ['BINARY','NOCASE','RTRIM']:
              raise TypeError("%s is not a valid SQLite collation" % kwargs['collate'])
          self.collation = kwargs.pop('collate').upper()
      super(CI_String, self).__init__(length=length, **kwargs)

@compiles(CI_String, 'sqlite')
def compile_ci_string(element, compiler, **kwargs):
  base_visit = compiler.visit_string(element, **kwargs) 
  if element.collation:
      return "%s COLLATE %s" % (base_visit, element.collation) 
  else:
      return base_visit

新的字符串类型可以像往常一样用于创建表:

just_a_table = Table('table_name', metadata,
               Column('case_insensitive', CI_String(8, collate='NOCASE'), nullable=False))

希望有人觉得这个方法有用!

9

在SQLAlchemy 0.8版本中,他们为所有字符串类型添加了一个叫做排序规则的参数。现在,COLLATE这个关键词被多个数据库支持,包括MySQL、SQLite和Postgresql。你应该可以写出类似下面的代码:

my_table = Table('table_name', meta,
                 Column('my_column', String(255, collation='NOCASE'),
                 nullable=False))

https://bitbucket.org/zzzeek/sqlalchemy/issues/2276

3

SQLite确实允许在文本字段上使用NOCASE排序规则

SQLite version 3.6.22
sqlite> create table me (name text collate nocase);
sqlite> .schema
CREATE TABLE me (name text collate nocase);
sqlite> insert into me values("Bob");
sqlite> insert into me values("alice");
sqlite> select * from me order by name;
alice
Bob

而SQLalchemy在架构中有一个collation()操作符,但我不太确定什么时候使用它。

撰写回答