我需要从“WHERE”子句中检索表父子关系,如下所示:
select ... large list of fields with aliases ...
from ... list of joined tables ...
where ((`db_name`.`catalog`.`group` = `db_name`.`catalog_group`.`iden`)
and (`db_name`.`catalog`.`iden` = `db_name`.`catalog_sub`.`parent`))
是否有一些正则表达式从每个条件中获取标识符?比如左边的数组元素[0] =表格,元素[1]是右边的表格。 Ident的名字可能是任何名字。因此,只有像'where''和''='这样的sql运算符可能是键。
非常感谢任何帮助。
CLARIFY
我不想通过WHERE子句从WHERE子句获取引用。我只是想要参考。所以我可以看到可能有正则表达式替换所有序列
`.`
到
.
然后按
匹配所有反对的对` @ ` = ` @ `
默认情况下,任何可能查询中始终存在标识符的反引号。默认情况下,所有字符串值都用双引号括起来。我认为这对正则表达式大师来说不是一项复杂的任务。提前谢谢。
PS这是因为myISAM引擎不支持我手动恢复的引用。
结束于:
public function initRef($q) {
$s = strtolower($q);
// remove all string values within double quotes
$s = preg_replace('|"(\w+)"|', '', $q);
// split by 'where' clause
$arr = explode('where', $s);
if (isset($arr[1])) {
// remove all spaces and parenthesis
$s = preg_replace('/\s|\(|\}/', '', $arr[1]);
// replace `.` with .
$s = preg_replace('/(`\.`)/', '.', $s);
// replace `=` with =
$s = preg_replace("/(`=`)/", "=", $s);
// match pairs within ticks
preg_match_all('/`.*?`/', $s, $matches);
// recreate arr
$arr = array();
foreach($matches[0] as &$match) {
$match = preg_replace('/`/', '', $match); // now remove all backticks
$match = str_replace($this->db . '.', '', $match); // remove db_name
$arr[] = explode('=', $match); // split by = sign
}
$this->pairs = $arr;
} else {
$this->pairs = 0;
}
}
答案 0 :(得分:2)
使用正则表达式似乎对您没有帮助。如果有子查询怎么办?如果您的查询包含一个包含文本“WHERE”的字符串,该怎么办? Hakre在上面的评论中提到过它,但你最好的选择是使用可以解释你的SQL的东西,这样你才能找到真正合适的WHERE子句和什么不是。
如果你坚持以“错误”的方式而不是使用一些上下文感知解析器,你必须找到WHERE子句,例如:
$parts = explode('WHERE', $query);
假设查询中只有一个WHERE子句,$parts[1]
将包含WHERE以后的所有内容。之后你必须检测所有可能跟随的有效子句,如ORDER BY,GROUP BY,LIMIT等,并在那里中断你的字符串。像这样:
$parts = preg_split("/(GROUP BY|ORDER BY|LIMIT)|/", $parts[1]);
$where = $parts[0];
您必须检查文档中的SQL风格以及要支持的查询类型(SELECT,INSERT,UPDATE等),以获取要拆分的完整关键字列表。
之后,它可能有助于删除所有括号,因为优先级与您的问题无关,并且它们使解析更难。
$where = preg_replace("/[()]/", "", $where);
从那时起,您必须再次拆分以找到所有单独的条件:
$conditions = preg_split("/(AND|OR|XOR)/", $where);
最后,您必须拆分运算符以获取右侧和左侧值:
foreach ($conditions as $c)
{
$idents = preg_split("/(<>|=|>|<|IS|IS NOT)/");
}
您必须检查运营商列表并在需要时添加。 $idents
现在包含所有可能的标识符。
您可能需要注意,其中一些步骤(至少在最后一步)还需要修剪字符串才能正常工作。
免责声明:,我认为这是一个非常糟糕的主意。此代码仅在只有一个WHERE子句时才有效,即使这样,它依赖于很多假设。复杂的查询可能会破坏此代码。请改用SQL解析器/解释器。