2

我需要从“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`))

是否有一些正则表达式可以从每个条件中获取标识符?在左侧的数组 element[0] = table 中,element[1] 是右侧的表格。Ident 的名称可以是任何名称。所以只有像 'where' 'and' '=' 这样的 sql 运算符可能是键。

任何帮助将不胜感激。

阐明

我不想通过 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;
    }

}
4

1 回答 1

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 解析器/解释器。

于 2013-08-20T15:43:30.720 回答