正则表达式问题

时间:2011-09-09 14:35:29

标签: php regex

我有这样的查询

SELECT a, (SELECT b FROM w), (SELECT c FROM x) FROM y WHERE a IN (SELECT d FROM z)

我希望将其转换为

SELECT COUNT(*) FROM y WHERE a IN (SELECT d FROM z)
在PHP中

这是一个样本,quires与此不同。

实际上,正则表达式只能用COUNT(*)替换第一个SELECT和FROM对之间的所有内容,但之后不要触摸SELECT。并且还必须考虑第一对内部还有一些其他SELECT FROM对并替换它们。

我现在用它

preg_replace('/SELECT (.*?) FROM/', 'SELECT COUNT(*) AS count FROM', $sql, 1)

但它没有在第一个SELECT * FROM

中检测到SELECT

4 个答案:

答案 0 :(得分:2)

假设您使用正则表达式将SELECTFROM之间的所有内容替换为COUNT(*)。使用简单的正则表达式模式,您可以通过两种不同的方式实现:

  1. 贪婪地匹配SELECTFROM
  2. 之间的所有内容
  3. 懒洋洋地匹配SELECTFROM
  4. 之间的所有内容

    让我们以你的例子输入:

    SELECT f1, f2, (SELECT f3 FROM t2) FROM t1 WHERE f1 IN (SELECT f4 FROM t)
    

    选项1符合以下条件:

    SELECT f1, f2, (SELECT f3 FROM t2) FROM t1 WHERE f1 IN (SELECT f4 FROM
    

    (第一个SELECT和最后一个FROM

    和选项2将匹配以下内容:

    SELECT f1, f2, (SELECT f3 FROM
    

    (第一个SELECT和第一个FROM

    用其他东西替换任何一种模式都会破坏你的SQL。当然,有更多“聪明”的方法来创建一个模式来解释这个特定的SQL输入,但我很确定,对于每个“智能”正则表达式,我(或其他人)将很容易找到一个可以“获得”的SQL脚本“由它打破。

    您可能会考虑使用递归模式,但是编写和维护很麻烦,而且它们也可以像这样破坏SQL代码:

    SELECT ... WHERE x='FOO WHERE BAR' ...
    

    (包含关键字的文字字符串)

    SELECT ... WHERE ...     -- FOO WHERE BAR
    

    (包含关键字的评论)

    所以,我对你的回答是:不要使用正则表达式。请改用某种SQL parser

答案 1 :(得分:1)

preg_replace似乎有点矫枉过正。为什么不使用str_replace或更好,str_ireplace


$sql = 'SELECT f1, f2, (SELECT f3 FROM t2) FROM t1 WHERE f1 IN (SELECT f4 FROM t)';
$fixed_sql = str_ireplace('f1, f2, (SELECT f3 FROM t2)', 'COUNT(*)', $sql);

如果查询总是不一样,您可以:


$sql = 'SELECT f1, f2, (SELECT f3 FROM t2) FROM t1 WHERE f1 IN (SELECT f4 FROM t)';
$fixed_sql = 'SELECT COUNT(*) ' . substr($sql, strpos($sql, ' FROM');

(未经测试,但概念相同)。

答案 2 :(得分:1)

怎么样:

$sql = preg_replace("/^.*( FROM t1)/", "SELECT COUNT(*)$1", $sql);

答案 3 :(得分:1)

对于您提供的特定模式:

SELECT ... (...) FROM ...

以下作品:

$sql = preg_replace('/^SELECT .*\(.*\) (FROM.*)$/', 'SELECT COUNT(*) $1', $sql);

但正如@Bart所指出的,任何偏离此模式的行为都会破坏您的SQL。