如何清理此SELECT查询?

时间:2009-02-25 19:20:54

标签: php sql mysql user-defined-functions

我在具有完全root访问权限的专用服务器(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参数传递的内容。

5 个答案:

答案 0 :(得分:3)

  

将WHERE条件修复为不那么令人反感的最佳选择是什么?

在应用程序层中执行替换,没有调用该逻辑在数据库中。使它成为一个普通的旧PHP函数。

ETA:唉,我明白你的意思了。你被填充了,剩下的就是“事实上数据库永远不应该被构造成首先需要这样的选择”! :-)你可以将REPLACE移动到存储的作品(CREATE FUNCTION)...这肯定会使查询看起来更好,但它确实在地毯下扫除了问题因为它仍然需要扫描和处理整个表以进行SELECT查询。我不认为你可以在不改变架构的情况下做得更好,抱歉。

(我猜这是一个从文本标题中获取'清理'ID样式标记的函数?通常你确实在一个普通的旧PHP函数中这样做,并将它作为一个单独的列存储'真实'标题。然后你可以轻松地选择它,并将其作为性能索引。)

答案 1 :(得分:2)

查看正则表达式库:

具体做法是:

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

答案 2 :(得分:1)

亲爱的,这很有趣。以下是对strSomeField的作用的总结:

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

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

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

  剥离字符之后

  与之前的情况相符   作为URI参数传递。

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

请勿将产品名称用作密钥!

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

这不是数据库问题。这是设计问题。我说错了。