2

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

4

5 回答 5

3

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

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

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

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

于 2009-02-25T19:37:06.160 回答
2

查看正则表达式库:

具体来说:

REGEXP_REPLACE?(text, pattern, replace ...)
于 2009-02-25T19:34:26.370 回答
1

哦,亲爱的,这是一个有趣的。以下是它对 strSomeField 所做的事情的总结:

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

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

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

于 2009-02-25T20:08:21.610 回答
0

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

于 2009-02-26T11:57:09.753 回答
0

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

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

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

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

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

于 2010-05-31T05:13:19.393 回答