Есть ли способ поиска по всем таблицам в базе данных MySQL? - PullRequest
2 голосов
/ 04 декабря 2010

В основном у меня есть база данных, полная таблиц, и я хочу просмотреть их все, пока не найду результат, соответствующий моему поисковому запросу.Есть ли способ сделать это?Или, по крайней мере, команда для возврата всех имен таблиц, чтобы я мог их перебирать, пока не найду правильное значение?

спасибо!

Ответы [ 6 ]

3 голосов
/ 05 декабря 2010

аааа, поисковики. Захватывающий предмет, но я бы предпочел построить что-то с помощью внутреннего интеллекта, а не использовать метод грубой силы. Да - проверка каждой таблицы / столбца в базе данных является грубой силой и может привести к медлительности и ложным срабатываниям.

Позвольте мне представить вам кое-что, что я бы использовал вместо этого. С помощью приведенного ниже решения каждую таблицу / столбец, который стоит сканировать, необходимо добавить вручную, но все остальное происходит автоматически. Вот использование:

$e = new SearchEngine();
$e->addTable('users', 'id', 'login'); // table, primary key name, column to be searched in
$e->addTable('users', 'id', 'last_name');
$e->addTable('towns', 'id', 'name');

print_r($e->search('austin')); // we search for exact match for word "austin"

А вот как это было реализовано:

class SearchEngine {

    protected $tables = array();

    public function addTable($table, $key, $column) {
        $this->tables[] = array(
            'table' => $table,
            'key' => $key,
            'column' => $column
        );
    }

    public function search($term) {
        $q = array();
        foreach ($this->tables as $t) {
            list($table, $key, $column) = $t;
            $q[] = "
                SELECT
                    $key AS searched_key,
                    '$key' AS searched_key_name,
                    '$table' AS searched_table,
                    '$column' AS searched_column,
                    $column AS searched_value
                FROM $table
                WHERE $column = $term
            ";
        }
        $sql = implode(' UNION ', $q);
        // query the database
        // return results
    }

} // class SearchEngine

Давайте проанализируем пример вывода:

searched_key | searched_key_name | searched_table | searched_column | searched_value
-------------+-------------------+----------------+-----------------+---------------
         276 |                id | users          | login           | austin
        1782 |                id | users          | last_name       | austin
          71 |                id | towns          | name            | austin

Из приведенной выше таблицы видно, что фраза «Остин» была найдена в таблице users, столбце login (первичный ключ 276) и столбце last_name (первичный ключ 1782). Он также был найден в таблице towns в столбце name (первичный ключ 71);

Такой результат поиска может быть достаточным для вас. Или же вы можете дополнительно обработать список, чтобы выбрать полную строку из каждой таблицы:

$out = array();
foreach ($rows as $row) {
    $sql = "
        SELECT * FROM {$row['searched_table']}
        WHERE {$row['searched_key_name']} = {$row['searched_key']}
        LIMIT 1
    ";
    // query the database
    // append result to $out array
}
return $out;

Таким образом, вы получите полный результат поиска (в отличие от промежуточных результатов из предыдущей таблицы):

id: 276, login: austin, last_name: Powers, email: austin.powers@gmail.com
id: 1782, login: michael, last_name: austin, email: michael.e@gmail.com
id: 71, name: austin, state: texas, country: usa

Поскольку текущая реализация ограничена фиксированным оператором сравнения (WHERE field = value), вы можете захотеть внести некоторую гибкость здесь. Если это так, оператор поиска должен быть делегирован во внешний класс и вставлен в search() функцию:

public function search(SearchOperator $operator, $term) {
...

Затем необходимо учитывать SearchOperator, заменив условие WHERE на следующее:

WHERE {$operator->toSQL($column, $term)}

Теперь давайте сосредоточимся на реализации SearchOperator. Поскольку реализация оператора предоставляет только один метод, а именно toSQL, нам не нужен полный класс или даже абстрактный класс. В этом случае интерфейса будет достаточно:

interface SearchOperator {

    public function toSQL($column, $term);

} // interface SearchOperator

И давайте определим пару реализаций, представляющих операторы = (равно) и LIKE:

class Equals implements SearchOperator {

    public function toSQL($column, $term) {
        return "$column = '$term'";
    }

} // class Equals

class Like implements SearchOperator {

    public function toSQL($column, $term) {
        return "$column LIKE '$term'";
    }

} // class Like

Естественно, возможна любая другая реализация - подумайте о классах, называемых StartsWith, EndsWith или DoesNotContain.

См. Использование обновленного решения:

$e = new SearchEngine();
$e->addTable('users', 'id', 'login');
$e->addTable('users', 'id', 'last_name');
$e->addTable('towns', 'id', 'name');

print_r($e->search(new Like(), 'austin%')); // here we search for columns being LIKE 'austin%'

Пора оставить несколько заключительных замечаний:

  • Приведенные выше примеры неполны. Код запроса к базе данных был опущен для ясности.
  • SQL, используемый в примерах, не очищает входные данные. Я настоятельно призываю вас использовать подготовленные операторы со связанными параметрами, чтобы избежать огромного риска для безопасности.
  • Алгоритм поиска, представленный выше, является наивным. Некоторая оптимизация может быть сделана (то есть группировка запросов, ссылающихся на одну и ту же таблицу). Но не оптимизируйте преждевременно - подождите, пока это не станет реальной проблемой.

Надеюсь, это было полезно.

1 голос
/ 04 декабря 2010

Очень плохая идея. Однако, если вам нужно искать во всех таблицах (и вы используете MySQL), вы можете получить список с:

SHOW TABLES;

А затем переберите каждый из них и (при условии, что вы знаете столбцы) запросите их.

0 голосов
/ 25 октября 2017

Есть хорошая библиотека для чтения всех таблиц, ridona

0 голосов
/ 04 декабря 2010

Вы можете получить все таблицы в вашей базе данных с помощью

SHOW TABLES;

Затем вы можете просмотреть таблицы и найти структуру каждой таблицы с помощью

DISPLAY table_name;

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

0 голосов
/ 04 декабря 2010

Как уже говорили другие, из словаря метаданных можно извлечь все имена таблиц и имена их столбцов.Взгляните на базу данных "information_schema".Вы можете получить список таблиц, по которым вы можете перебирать.

Но есть вероятность, что вы используете базу данных неправильно.Мы не запрашиваем базу данных, мы запрашиваем модель данных.Модель данных реализована в виде набора таблиц / представлений и т. Д.

Можете ли вы дать нам некоторую справочную информацию о том, зачем вам это нужно?Может быть, есть лучшие альтернативы?

0 голосов
/ 04 декабря 2010

Полагаю, вы могли бы использовать полнотекстовый поиск Mysql для этого?

...