3

我想用 php 检测 mysql 查询中的所有表。我看到了适用于普通查询的 mysql_field_table() 函数。但是当您为表使用替代名称(table_name AS new_name)时,它返回替代名称而不是真实名称,我如何通过正则表达式修复它。但现在我的问题是这样的高级查询:

SELECT mail_id, mail_date, mail_from, mail_to, mail_subject, (
            (
            SELECT COUNT(*)
            FROM `sys_messagecenter_qmails`
            WHERE qmail_mail_id = mail_id
            ) + (
            SELECT COUNT(*)
            FROM `sys_messagecenter_rels`
            WHERE rel_mail_id = mail_id
            )
            ) AS email_total, (
            SELECT COUNT(*)
            FROM `sys_messagecenter_rels`
            WHERE rel_mail_id = mail_id
            ) AS email_sent, (
            SELECT COUNT(*)
            FROM `sys_messagecenter_rels`
            INNER JOIN `sys_email_receives` ON receive_reply_to = rel_sent_id
            WHERE rel_mail_id = mail_id
            ) AS email_reply FROM `sys_messagecenter_emails` WHERE mail_draft='No' 
ORDER BY mail_id ASC LIMIT 0,10 

现在我想我需要一些正则表达式来检测查询中的所有真实表名。或任何其他完美的解决方案。我怎样才能做到这一点?

4

4 回答 4

3

抱歉...这里有一个提取它的解决方案(如果您的查询在$query

if(preg_match_all('/((FROM|JOIN) `(.*)`)/', $query, $matches)) {
    $tables = array_unique($matches[3]);
    print_r($tables);
}
于 2012-06-13T09:19:47.450 回答
3

我还需要从查询中提取表名。然后我编写自己的脚本,该脚本几乎适用于每个基本查询。

$tables = array();
$sql ="SELECT m.`id` FROM my_table m INNER JOIN mytable_2 m2 ON(m.`id` = m2.`m_id`) ";

    $query_structure = explode( ' ', strtolower( preg_replace('!\s+!', ' ', $sql) ) );

    $searches_from = array_keys( $query_structure , 'from');
    $searches_join = array_keys( $query_structure , 'join');
    $searches_update = array_keys( $query_structure , 'update');
    $searches_into = array_keys( $query_structure , 'into');
    $searches = array_merge($searches_join , $searches_from , $searches_update , $searches_into );
    foreach($searches as $search ){
        if(isset($query_structure[$search+1])){
            $tables[] = trim( $query_structure[$search+1] , '` ');
        }
    }
    print_r($tables);

希望这会有所帮助

于 2016-03-20T12:16:49.187 回答
1

我使用下面的代码(a 是 var_dump 等效项):

/**
 * Only works if the table names and database names don't have a space or a dot in them.
 */

$queries = [
    "select * from my_table",
    "select * from `my_table`",
    "select * from my_db.my_table",
    "select * from my_db.`my_table`",
    "select id from my_table where x=2",
    "select id from my_table mt inner join other_table ot on ot.my_table_id=mt.id where mt.x=2",
    "SELECT mail_id, mail_date, mail_from, mail_to, mail_subject, (
            (
            SELECT COUNT(*)
            FROM `sys_messagecenter_qmails`
            WHERE qmail_mail_id = mail_id
            ) + (
            SELECT COUNT(*)
            FROM `sys_messagecenter_rels`
            WHERE rel_mail_id = mail_id
            )
            ) AS email_total, (
            SELECT COUNT(*)
            FROM `sys_messagecenter_rels`
            WHERE rel_mail_id = mail_id
            ) AS email_sent, (
            SELECT COUNT(*)
            FROM `sys_messagecenter_rels`
            INNER JOIN `sys_email_receives` ON receive_reply_to = rel_sent_id
            WHERE rel_mail_id = mail_id
            ) AS email_reply FROM `sys_messagecenter_emails` WHERE mail_draft='No' 
ORDER BY mail_id ASC LIMIT 0,10 ",
      "select count(*) as count from (
select 
user_id,
permission_group_id,
concat(uhpg.user_id, '. ', u.pseudo) as user_id_plus,
concat(uhpg.permission_group_id, '. ', pg.name) as permission_group_id_plus
from lud_user_has_permission_group uhpg
inner join lud_user u on uhpg.user_id=u.id
inner join lud_permission_group pg on uhpg.permission_group_id=pg.id
) as ttt",
];


$tables = [];

foreach ($queries as $query) {
    a($query);
    if (preg_match_all('!((FROM|JOIN)\s([\S]+))!i', $query, $matches)) {
        $tables = array_unique($matches[3]);
        array_walk($tables, function (&$v) {
            $p = explode('.', $v, 2);
            $v = array_pop($p);
            $v = trim($v, '`');
        });
        $tables = array_filter($tables, function ($v) {
            return ('(' !== $v);
        });
        a($tables);
    }
}

这给出了以下输出:

string(22) "select * from my_table"

array(1) {
  [0] => string(8) "my_table"
}

string(24) "select * from `my_table`"

array(1) {
  [0] => string(8) "my_table"
}

string(28) "select * from my_db.my_table"

array(1) {
  [0] => string(8) "my_table"
}

string(30) "select * from my_db.`my_table`"

array(1) {
  [0] => string(8) "my_table"
}

string(33) "select id from my_table where x=2"

array(1) {
  [0] => string(8) "my_table"
}

string(89) "select id from my_table mt inner join other_table ot on ot.my_table_id=mt.id where mt.x=2"

array(2) {
  [0] => string(8) "my_table"
  [1] => string(11) "other_table"
}

string(810) "SELECT mail_id, mail_date, mail_from, mail_to, mail_subject, (
            (
            SELECT COUNT(*)
            FROM `sys_messagecenter_qmails`
            WHERE qmail_mail_id = mail_id
            ) + (
            SELECT COUNT(*)
            FROM `sys_messagecenter_rels`
            WHERE rel_mail_id = mail_id
            )
            ) AS email_total, (
            SELECT COUNT(*)
            FROM `sys_messagecenter_rels`
            WHERE rel_mail_id = mail_id
            ) AS email_sent, (
            SELECT COUNT(*)
            FROM `sys_messagecenter_rels`
            INNER JOIN `sys_email_receives` ON receive_reply_to = rel_sent_id
            WHERE rel_mail_id = mail_id
            ) AS email_reply FROM `sys_messagecenter_emails` WHERE mail_draft='No' 
ORDER BY mail_id ASC LIMIT 0,10 "

array(4) {
  [0] => string(24) "sys_messagecenter_qmails"
  [1] => string(22) "sys_messagecenter_rels"
  [4] => string(18) "sys_email_receives"
  [5] => string(24) "sys_messagecenter_emails"
}

string(360) "select count(*) as count from (
select 
user_id,
permission_group_id,
concat(uhpg.user_id, '. ', u.pseudo) as user_id_plus,
concat(uhpg.permission_group_id, '. ', pg.name) as permission_group_id_plus
from lud_user_has_permission_group uhpg
inner join lud_user u on uhpg.user_id=u.id
inner join lud_permission_group pg on uhpg.permission_group_id=pg.id
) as ttt"

array(3) {
  [1] => string(29) "lud_user_has_permission_group"
  [2] => string(8) "lud_user"
  [3] => string(20) "lud_permission_group"
}


于 2019-12-19T05:43:30.410 回答
0

这不是最优雅的解决方案,但已经通过了我迄今为止运行的所有测试:

function get_table_name($query) {

    $query = trim(str_replace(PHP_EOL, ' ', $query));

    $table = '';

    if(strtolower(substr($query, 0, 12)) == 'create table') {
        $start = stripos($query, 'CREATE TABLE') + 12;
        $end = strpos($query, '(');
        $length = $end - $start;
        $table = substr($query, $start, $length);
    }
    elseif(strtolower(substr($query, 0, 6)) == 'update') {
        $end = stripos($query, 'SET');
        $table = substr($query, 6, $end);
    }
    elseif(strtolower(substr($query, 0, 11)) == 'alter table') {
        $parts = explode(' ', $query);
        $table = $parts[2];
    }
    elseif(strtolower(substr($query, 0, 11)) == 'insert into') {
        $parts = explode(' ', $query);
        $table = $parts[2];
    }
    elseif(strtolower(substr($query, 0, 12)) == 'create index') {
        $parts = explode(' ', $query);
        $table = $parts[4];
    }
    elseif(strtolower(substr($query, 0, 6)) == 'select') {
        $parts = explode(' ', $query);
        foreach($parts as $i => $part) {
            if(trim(strtolower($part)) == 'from') {
                $table = $parts[$i + 1];
                break;
            }
        }
    }
    elseif(strtolower(substr($query, 0, 29)) == 'create unique clustered index') {
        $parts = explode(' ', $query);
        $table = $parts[6];
    }
    elseif(strtolower(substr($query, 0, 22)) == 'create clustered index') {
        $parts = explode(' ', $query);
        $table = $parts[5];
    }
    elseif(strtolower(substr($query, 0, 15)) == 'exec sp_columns') {
        $parts = explode(' ', $query);
        $table = str_replace("'", '', $parts[2]);
    }
    elseif(strtolower(substr($query, 0, 11)) == 'delete from') {
        $parts = explode(' ', $query);
        $table = str_replace("'", '', $parts[2]);
    }

    return trim(str_replace(['`', '[', ']'], ['', '', ''], $table));

}
于 2018-08-20T08:24:43.417 回答