我有这样的查询
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答案 0 :(得分:2)
假设您使用正则表达式将SELECT
和FROM
之间的所有内容替换为COUNT(*)
。使用简单的正则表达式模式,您可以通过两种不同的方式实现:
SELECT
和FROM
SELECT
和FROM
让我们以你的例子输入:
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。