Рассмотрим эти три оператора mysql:
select * from Users; select id, title, value from Blogs; select id, feelURL, feelTitle from Feeds where id = 1;
Теперь я не очень хорошо разбираюсь в REGEX, но хочу получить имя таблицы из запроса mysql. Может ли кто-нибудь создать его для меня с небольшим объяснением.
Благодаря,
Пытаться:
preg_match('/\bfrom\b\s*(\w+)/i',$query,$matches)
Это не будет работать, если запрос содержит более 1 таблицы.
В основном регулярное выражение выполняет поиск полного слова FROM
в запросе и выбирает следующее слово в качестве имени таблицы.
Фактически вы можете использовать MySQL в качестве синтаксического анализатора и получать теги tablenames в своем запросе независимо от того, насколько сложна синтаксис 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 | | +----+-------------+---------+-------+---------------+---------+---------+------+------+-------------+
Теперь вы можете просто обрабатывать результаты, как и любой другой запрос.
Наивная реализация будет такой:
preg_match("/\s+from\s+`?([az\d_]+)`?/i", $query, $match); echo $query . " => " . $match[1] . "\n";
Это сломается, если у вас есть подзапрос в списке SELECT (и, вероятно, в нескольких других случаях). Или когда ваше имя таблицы содержит символы рядом с az, номерами и символами подчеркивания.
Правильный анализ SQL не является тривиальным.
Для строки запроса, которую вы указали, необходимо выполнить следующее:
preg_match_all('/from (\w+)/', $query, $tables); print_r($tables[1]); [0] => Users [1] => Blogs [2] => Feeds
Но, как уже отмечалось в комментарии, создание полноценного анализатора SQL является нетривиальной задачей. Не ожидайте, что это будет использоваться по любым и всем запросам, которые вы бросаете против него.
Хотелось бы, чтобы я видел это раньше … Как и люди выше меня, это нетривиальные синтаксические выражения 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; }
Надеюсь, что кто-то поможет …
Это должно сделать это:
(SELECT|DELETE|UPDATE|INSERT INTO) (\*|[A-Z0-9_]+)(FROM)?([A-Z0-9_, ]+)
Он будет работать с выбранным обновлением удаления и вставкой. Если вы используете tablename1, tablename2, он вернет его как массив