2010-03-18 53 views
2

表名考虑这三个MySQL的语句:PHP:使用正则表达式来得到一个MySQL查询

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

现在,在正则表达式的即时通讯不是很好,但我想从MySQL查询获取表名。有人可能会给我一个小小的解释。

感谢,

+0

可能不是,SQL不是一个完全平凡的语言,我想你基本上需要一个SQL解析器,而且我怀疑任何人都会想写一个那些有正则表达式的人。 – 2010-03-18 09:06:30

+0

你能解释一下为什么和你想要做什么吗?使用这些示例语句,使用正则表达式很容易,但只要语句稍微复杂一些(例如,连接,引用的表名等),这样的解决方案就会中断。如果您告诉我们目的是什么,那么可能会提出更好的解决方案。 – balpha 2010-03-18 09:13:11

+0

不确定你想要完成什么,但会更有用吗? [mysql_tablename](http://www.php.net/manual/en/function.mysql-tablename.php) – mcgrailm 2010-03-18 15:29:02

回答

2

尝试:

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

这不会工作,如果查询有超过100台。

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

+1

如何插入,更新等? – Mala 2011-11-07 02:16:25

0

你给的查询字符串,下面应该做的:

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

print_r($tables[1]); 

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

但是,像在评论已经指出,创造一个完全成熟的SQL语法分析程序是一个不平凡的任务。不要指望在任何和所有针对它的查询中都可以使用它。

1

一个天真的实施将是这样的:

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

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

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

正确解析SQL不是微不足道的。

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; 
} 

希望帮助别人......

+0

返回false positive是'table_name'是一个值的一部分(即:SELECT * FROM myTable WHERE column ='foo bar anotherTable';) – Toto 2010-10-21 09:04:42

+0

是的你是对的,但它处理多个表将打破其他正则表达式。根据我的经验,跨越多个表的选择语句比命名列中的另一个表更有可能。所以是的,不完美,但海事组织,更好。 – 2010-10-21 12:33:29

+0

顺便说一句,我也尝试写一个正则表达式,并且你必须考虑MySQL将接受插入的所有方式,例如所有这些工作(这是宽容语言的问题): FROM \'foo \'。\ 'bar \'WHERE FROM \'bar \'WHERE FROM \'foo \'。''bar \'WHERE FROM \'foo \'。''bar \'WHERE FROM foo.bar WHERE FROM bar WHERE ...(有大量的排列可能) 和语法随着插入语句,删除语句等而改变。这里没有任何正则表达式可以处理所有上述情况。 – 2010-10-21 15:18:56

4

实际上,你可以使用MySQL作为解析器和您的查询获得表名不管你的SQL语法有多复杂。

(对不起,这是给你的问题反应迟缓 - 我有同样的问题今天发现这个解决方案)

简单的前缀词的查询说明,并将结果集返回到PHP包括ID,SELECT_TYPE,表,类型,possible_keys,钥匙,key_len,裁判,行外。第三列是查询中每个表的名称。

例如,如果您的查询是:

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 |    | 
+----+-------------+---------+-------+---------------+---------+---------+------+------+-------------+ 

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

0

这应做到:

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

将作品与选择删除更新和插入。如果你使用tablename1,tablename2它会将它作为数组返回