【问题标题】:How can I clean up this SELECT query?如何清理此 SELECT 查询?
【发布时间】:2009-02-25 19:20:54
【问题描述】:

我在具有完全根访问权限的专用服务器(Ubuntu Server 8.10)上运行 PHP 5 和 MySQL 5。我正在清理一些我继承的 LAMP 代码,并且我有大量使用这种构造的 SQL 选择:

SELECT ... FROM table WHERE
  LCASE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
    strSomeField, ' ', '-'), ',', ''), '/', '-'), '&', ''), '+', '')
  ) = $somevalue

忽略这样一个事实,即从一开始就不应该构建数据库来要求这样的选择,并且需要对 $somevalue 字段进行参数化以堵塞巨大的安全漏洞,我修复 WHERE 的最佳选择是什么条件变成不那么令人反感的东西?如果我使用的是 MSSQL 或 Oracle,我会简单地组合一个用户定义的函数,但是我对 MySQL 的经验比较有限,而且我以前没有用它构建过 UDF,尽管我很高兴编写 C 代码。

更新:对于所有已经在原始代码中对此感到惊讶的人来说,$somevalue 实际上类似于 $GET['product']——在主题。在这种情况下,选择是通过产品名称从数据库中拉回产品——在删除字符之后,它与之前可以作为 URI 参数传递的内容相匹配。

【问题讨论】:

  • 这个已经提交给thedailywtf.com了吗?
  • 那个代码很可爱!我 5 岁的儿子知道更好的预防 SQL 注入的方法。
  • 你能对搜索值做反向转换吗?也许这可以成为使所有条目一致的过程的一部分?

标签: php sql mysql user-defined-functions


【解决方案1】:

将 WHERE 条件修复为不那么冒犯的最佳选择是什么?

在应用层进行替换,数据库中不需要该逻辑。让它成为一个普通的旧 PHP 函数。

ETA:啊,我明白你的意思了。那么你就被塞满了,剩下的就是“数据库不应该被构建为首先需要这样的选择这一事实”! :-) 您可以将 REPLACE 移到存储的产品中 (CREATE FUNCTION)...这肯定会使查询看起来更好,但它确实像它一样扫除了地毯下的问题仍然需要扫描和处理整个表以进行 SELECT 查询。抱歉,如果不更改架构,我认为您无法做得更好。

(我猜这是一个从文本标题中获取“已清理”ID 样式标记的函数?通常你确实会在一个普通的旧 PHP 函数中执行此操作,并将其存储为与'real' 标题。然后您可以轻松选择它,并为性能编制索引。)

【讨论】:

  • 怎么样?鉴于替换函数应用于数据库中的字段,而不是 PHP 变量
  • +1,更改表以添加过滤列并运行更新,此替换所有表一次。还在插入新记录时添加替换。
【解决方案2】:

查看正则表达式库:

具体来说:

REGEXP_REPLACE?(text, pattern, replace ...)

【讨论】:

    【解决方案3】:

    天哪,这很有趣。以下是它对 strSomeField 所做的总结:

    • 空格和正斜杠变成连字符
    • 逗号、& 和加号已删除
    • 转换为小写

    如果不添加 MarkusQ 链接的 regexp_replace 用户定义函数,这在 MySQL 中是不容易做到的,我认为这需要重新编译 MySQL。

    您是否可以选择简单地处理表中的所有数据,这样就没有必要了?创建一个 PHP 脚本以选择 strSomeField 中的所有值,执行与我上面总结的相同的处理,并使用新值更新行。或者这会破坏应用程序的其他部分吗?

    【讨论】:

      【解决方案4】:

      如果您确实使用预处理的 strSomeField 列创建了一个新字段,则应添加一个触发器,该触发器会在 strSomeField 更改时自动更新它。可能会消除一些头痛。

      【讨论】:

        【解决方案5】:

        去掉字符后 匹配以前可能的内容 作为 URI 参数传递。

        哦。同样的陷阱一次又一次。

        不要使用产品名称作为关键字!

        您不认为 SO 作者的经验不如您吗?
        但请查看 SO 问题网址:
        stackoverflow.com/questions/587422/how-can-i-clean-up-this-select-query
        他们使用数字键,其余的仅用于装饰。
        因此,可以随时编辑名称,但页面将保持不变。当然,没有像你这样的问题。

        不是数据库问题。是设计问题。我想说的错。

        【讨论】:

        • 是的,最后我只是用一个函数把它扫到了地毯下,因为实际上正确地修复它会破坏一切。整个系统使用一个单一的巨神类,这样的漏洞百出——至少现在看起来不那么冒犯了,读起来更干净。
        猜你喜欢
        • 1970-01-01
        • 2011-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-27
        • 1970-01-01
        • 2019-03-07
        相关资源
        最近更新 更多