PHP:使用REGEX从mysql查询中获取表名

时间:2010-03-18 09:01:46

标签: php regex preg-match

考虑这三个mysql语句:

select * from Users;
select id, title, value from Blogs;
select id, feelURL, feelTitle from Feeds where id = 1; 

现在我不是很擅长REGEX,但我想从mysql查询中获取表名。有人可能会为我创建一个有一点解释。

谢谢,

6 个答案:

答案 0 :(得分:5)

实际上,您可以使用MySQL作为解析器,无论SQL语法有多复杂,都可以在查询中获取表名。

(很抱歉,这是对你的问题的迟到回复 - 我今天遇到了同样的问题并找到了这个解决方案。)

只需在查询前加上单词EXPLAIN,返回给PHP的结果集将包括id,select_type,table,type,possible_keys,key,key_len,ref,rows,Extra。第三列是查询中每个表的名称。

例如,如果您的查询是:

select count(*) from ey_def left join ey_rels on def_id=item_id;

使用:

explain select count(*) from ey_def left join ey_rels on def_id=item_id;

MySQL将把它返回给PHP:

+----+-------------+---------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table   | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+---------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | ey_def  | index | NULL          | PRIMARY | 4       | NULL |   87 | Using index |
|  1 | SIMPLE      | ey_rels | ALL   | NULL          | NULL    | NULL    | NULL |  123 |             |
+----+-------------+---------+-------+---------------+---------+---------+------+------+-------------+

现在您可以像处理任何其他查询一样简单地处理结果。

答案 1 :(得分:2)

尝试:

preg_match('/\bfrom\b\s*(\w+)/i',$query,$matches)

如果查询包含多个表,则无效。

正则上,正则表达式在查询中搜索完整的单词FROM,并选择以下单词作为表名。

答案 2 :(得分:1)

一个天真的实现是:

preg_match("/\s+from\s+`?([a-z\d_]+)`?/i", $query, $match);

echo $query . " => " . $match[1] . "\n";

当你的SELECT字段列表中有一个子查询时,中断(可能还有其他一些情况)。或者,当您的表名包含a-z,数字和下划线旁边的字符时。

正确解析SQL并非易事。

答案 3 :(得分:0)

对于您提供的查询字符串,应执行以下操作:

preg_match_all('/from (\w+)/', $query, $tables);

print_r($tables[1]);

[0] => Users
[1] => Blogs
[2] => Feeds

但是就像已经在评论中指出的那样,创建一个完整的SQL解析器是一项非常重要的任务。不要指望这个可以用在针对它的任何和所有查询上。

答案 4 :(得分:0)

希望我早些看到这个......就像我上面的人所说的那样,这是非常简单的解析sql语句。要从sql字符串中选择表名,最好先获取所有表名,然后在sql中查找匹配项(假设数据库中没有一百万个表)。我碰巧手头有一个功能就是这样:

/*
  Takes a sql statement and attempts to get a table name from it.
  This assumes a database is already specified in the connection.

  [$sql]: string; SQL statement that was executed
  [$conn]: resource; MySQLi connection resource

  returns table name string
 */  
function get_table_names($sql,$conn){
    //declare variables
    $table_array = array();
    $table_string = "";

    //get all the table names in the selected database
    $sql2 = "SHOW TABLES";
    $result = mysqli_query($conn, $sql2);

    //display an error if something went wrong
    if (!$result) {
        echo "DB Error, could not list tables\n";
        echo 'MySQL Error: ' . mysqli_error($conn);
        exit;
    }

    //fetch the rows and push the table names into $table_array
    while ($row = mysqli_fetch_row($result)) {
        array_push($table_array, $row[0]);
    }

    //loop through all the tables in the database
    foreach($table_array as $table){
        if(strpos($sql,$table)){ //if match is found append to string
            $table_string .= " $table ";
        }
    }

    //return a string of table name matches
    return $table_string;
}

希望有人帮助......

答案 5 :(得分:0)

这应该这样做:

(SELECT|DELETE|UPDATE|INSERT INTO) (\*|[A-Z0-9_]+)(FROM)?([A-Z0-9_, ]+)

它将与select delete update和insert一起使用。如果使用tablename1,tablename2,它将把它作为数组返回