PHP: использование REGEX для получения имени таблицы из запроса MySQL - PullRequest
3 голосов
/ 18 марта 2010

Рассмотрим эти три оператора mysql:

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

Сейчас я не очень хорош в REGEX, но я хочу получить имя таблицы из запроса mysql. Может ли кто-нибудь создать его для меня с небольшим объяснением?

Спасибо

Ответы [ 6 ]

5 голосов
/ 21 февраля 2011

На самом деле вы можете использовать MySQL в качестве анализатора и получать имена таблиц в своем запросе независимо от сложности синтаксиса SQL.

(Извините, что это поздний ответ на ваш вопрос - у меня сегодня была такая же проблема, и я нашел это решение.)

Просто добавьте ваш запрос к слову EXPLAIN, и набор результатов, возвращаемый PHP, будет включать id, select_type, table, type, возможных_ключей, ключ, key_len, ref, lines, 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 |             |
+----+-------------+---------+-------+---------------+---------+---------+------+------+-------------+

Теперь вы можете просто обработать результаты, как и любой другой запрос.

2 голосов
/ 18 марта 2010

Попробуйте:

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

Это не будет работать, если запрос содержит более 1 таблицы.

В основном регулярное выражение ищет в запросе полное слово FROM и выбирает в качестве имени таблицы следующее слово.

1 голос
/ 18 марта 2010

Наивная реализация будет такой:

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

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

Этот будет прерываться, когда у вас есть подзапрос в списке полей SELECT (и, возможно, в некоторых других случаях). Или когда имя вашей таблицы содержит символы, кроме a-z, цифры и подчеркивания.

Правильный анализ SQL не тривиален.

0 голосов
/ 28 марта 2017

Это должно сделать это:

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

Это будет работать с выберите удалить обновление и вставить. Если вы используете tablename1, tablename2, он вернет его в виде массива

0 голосов
/ 21 октября 2010

Хотелось бы, чтобы я видел это раньше ... Как говорили люди выше меня, это нетривиальный синтаксический анализ 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 голосов
/ 18 марта 2010

Для строки запроса, которую вы дали, должно выполняться следующее:

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

print_r($tables[1]);

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

Но, как уже указывалось в комментарии, создание полноценного парсера SQL является нетривиальной задачей. Не ожидайте, что это будет применимо к любому и всем запросам, которые вы бросаете против него.

...