【问题标题】:SQLAlchemy case insensitive IN based search query?SQLAlchemy 基于 IN 的搜索查询不区分大小写?
【发布时间】:2014-02-07 23:34:00
【问题描述】:

如何以安全的方式在 SQLAclhemy ORM 中进行不区分大小写的 IN 搜索?

我自己和我项目中的其他人都在寻找这个,但我们似乎找不到任何适合我们需要的东西。

在原始 SQL 中我可以做到:

 SELECT * FROM TABLENAME WHERE UPPER(FIELDNAME) IN (UPPER('foo'), UPPER('bar'));

..如果 FOO 和 BAR 在未知情况下不是用户输入。事实上,我担心以下几点:

  1. 安全性:我不希望 Bobby Tables (http://xkcd.com/327/) 以 SQL 注入攻击的形式进行访问。我找不到告诉我如何在 SQLAlchemy 中转义字符串的文档,否则我会觉得加入更安全字符串(但仍然觉得这样做很脏)。
  2. 速度主要是通过索引来处理的,但显然,在发出查询之前在 RAM 中进行大小写更正比告诉数据库执行它要快,所以除非我真的必须这样做,否则我不会在查询中执行 UPPER。然而,以上是展示我想要做的最好的方式。但是 sti;;,它不应该做任何疯狂的事情。
  3. 平台无关代码。我将在多种数据库类型上运行它——如果我对此事有任何发言权,它将经过全面测试——而且我不希望查询绑定到特定的 SQL 对话框。毕竟,这就是我使用 SQLAlchemy 的原因。 :)

如果它有帮助,由于我们使用其他库,我们目前绑定到 8.4 版本的 SQLAlchemy。

【问题讨论】:

    标签: python mysql sql sqlalchemy pyramid


    【解决方案1】:

    这应该完全编译...

    query( models.Object )\
    .filter( 
         sqlalchemy.func.upper( models.Object.fieldname )\
         .in_( (sqlalchemy.func.upper(foo) , sqlalchemy.func.upper(bar), ) )
    )\
    .all()
    

    1. 您也可以只传递大写文本。就个人而言,我会做in_( foo.uppercase() , bar.uppercase() )

    2. SqlAlchemy 与 DBAPI 一起将绑定参数传递到您的后端数据存储中。翻译——值被自动转义。


    如果你想做一个字符串列表,这样的事情应该可以工作

    .in_( [ i.upper() for i in inputs ] )
    .in_( [ sqlalchemy.func.upper(i) for i in inputs ] )
    

    只想补充一点,如果您想优化这些选择以提高速度,并且在 Postgres 或 Oracle 上,您可以创建一个“函数索引”

    CREATE INDEX table_fieldname_lower_idx ON table(lower(fieldname))
    

    查询规划器(在数据库中)将知道在搜索 lower(fieldname) 查询时使用该 lower(fieldname) 索引。

    【讨论】:

    • 如果我的输入是一个字符串列表呢?
    • 我的第一篇文章使用了错误的语法。 in_ 需要一个可迭代的。所以你可以扔一个列表,list_comprehension,生成器,lambda/map/etc。
    • 将其设置为答案;我的团队和 Bobby Table 的母亲都感谢您。
    • 谢谢。我应该补充一下,进行小写比较/存储通常更适合调试——它往往比大写更容易被人眼阅读。
    • 是的,但排序规则的问题在于它是一个特定于平台的问题,我们正努力使其尽可能与平台无关。
    猜你喜欢
    • 1970-01-01
    • 2019-03-15
    • 2013-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-02
    • 1970-01-01
    • 2023-03-07
    相关资源
    最近更新 更多