2010-12-03 6 views
2

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

спасибо!

+1

Я подозреваю, что это можно легко сделать с динамическим SQL. Запросите некоторую мета-таблицу со всеми именами таблиц и именами столбцов, затем пропустите этот набор результатов и запросите таблицы и столбцы, как вы хотите. Не публиковать в качестве ответа, потому что я не уверен, что это возможно в MySQL (я знаю, что подобные трюки работают в Oracle, хотя) – FrustratedWithFormsDesigner 2010-12-03 21:24:12

ответ

3

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

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

$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: [email protected] 
id: 1782, login: michael, last_name: austin, email: [email protected] 
id: 71, name: austin, state: texas, country: usa 

Поскольку текущая реализация ограничена фиксированным оператором сравнения (поле WHERE = значение), вы можете ввести некоторую гибкость здесь. Если да, то оператор поиска должен быть делегирована внешнему классу и вводили в 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

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

SHOW TABLES; 

А затем цикл по и (если вы знаете столбцы) запрашивать их.

+0

Могу ли я спросить, почему это плохая идея? Это просто ресурс? Вся база данных находится под 2000 строк, поэтому она относительно небольшая. – Parker 2010-12-03 21:30:30

0

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

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

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

0

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

SHOW TABLES; 

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

DISPLAY table_name; 

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

Смежные вопросы