如果它适合您的用例,您可以考虑在列上设置自定义排序规则,以便该列以不区分大小写的方式自动处理比较。
值得注意的是:
- 排序规则将应用于列上的所有查询
- 排序规则也适用于
ORDER BY
子句
- 排序规则可以直接在查询中指定,而不是在列上定义
- 排序规则定义往往是 RDBMS / 区域设置 / 特定语言 - 请参阅相关文档
- 排序规则名称可能无法在不同的 RDBMS 之间移植
- 可用的排序规则属性可能因 RDBMS 而异
换句话说,在使用此功能之前,请查阅您的 RDBMS 文档。
这个示例脚本展示了如何对 MySQL、Postgresql(注意特殊情况)和 Sqlite 使用排序规则;每个 RDBMS 返回查询值的所有三个可能结果。
import sqlalchemy as sa
from sqlalchemy import orm
data = {
'mysql': ('mysql:///test', 'utf8mb4_general_ci'),
'postgresql': ('postgresql:///test', 'coll'),
'sqlite': ('sqlite://', 'NOCASE'),
}
for dialect, (uri, collation) in data.items():
Base = orm.declarative_base()
class Test(Base):
__tablename__ = 't16573095'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.String(32, collation=collation))
engine = sa.create_engine(uri, echo=False, future=True)
Base.metadata.drop_all(engine)
if dialect == 'postgresql':
# Postgres collations are more complicated
# - read the docs!
with engine.begin() as conn:
conn.execute(sa.text('DROP COLLATION IF EXISTS coll'))
stmt = """CREATE COLLATION coll (provider='icu', locale='und-u-ks-level2', deterministic=false)"""
conn.execute(sa.text(stmt))
Base.metadata.create_all(engine)
Session = orm.sessionmaker(engine, future=True)
with Session.begin() as s:
instances = [Test(name=name) for name in ['GANYE', 'ganye', 'gAnYe']]
s.add_all(instances)
with Session() as s:
results = s.execute(sa.select(Test.name).where(Test.name == 'GaNyE')).scalars()
print(f'{dialect:-<12}')
for name in results:
print(name)
print('-' * 12)
要在查询中指定排序规则,请使用属性的collate方法:
with Session() as s:
query = sa.select(Test).where(Test.name.collate('coll') == 'GaNyE')
results = s.execute(query)