125

我正在使用 Flask-SQLAlchemy 从用户数据库中查询;然而,虽然

user = models.User.query.filter_by(username="ganye").first()

将返回

<User u'ganye'>

正在做

user = models.User.query.filter_by(username="GANYE").first()

返回

None

我想知道是否有办法以不区分大小写的方式查询数据库,以便第二个示例仍会返回

<User u'ganye'>
4

4 回答 4

242

您可以使用过滤器中的lowerorupper函数来实现:

from sqlalchemy import func
user = models.User.query.filter(func.lower(User.username) == func.lower("GaNyE")).first()

另一种选择是使用ilike而不是进行搜索like

.query.filter(Model.column.ilike("ganye"))
于 2013-05-15T19:44:13.680 回答
17

改进@plaes 的答案,如果您仅指定所需的列,这将使查询更短:

user = models.User.query.with_entities(models.User.username).\
filter(models.User.username.ilike("%ganye%")).all()

如果需要将 Flask 的 jsonify 用于 AJAX 目的,然后在您的 javascript 中使用data.result访问它,则上面的示例非常有用:

from flask import jsonify
jsonify(result=user)
于 2015-05-11T21:01:27.890 回答
7

你可以做

user = db.session.query(User).filter_by(func.lower(User.username)==func.lower("GANYE")).first()

或者你可以使用 ilike 功能

 user = db.session.query(User).filter_by(User.username.ilike("%ganye%")).first()
于 2019-05-08T05:36:06.203 回答
1

如果它适合您的用例,您可以考虑在列上设置自定义排序规则,以便该列以不区分大小写的方式自动处理比较。

值得注意的是:

  • 排序规则将应用于列上的所有查询
  • 排序规则也适用于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)

要在查询中指定排序规则,请使用属性的collat​​e方法:

with Session() as s:
    query = sa.select(Test).where(Test.name.collate('coll') == 'GaNyE')
    results = s.execute(query)
于 2022-01-20T22:18:51.077 回答