Как найти значение в столбце mysql

If you are avoiding stored procedures like the plague, or are unable to do a mysql_dump due to permissions, or running into other various reasons.

I would suggest a three-step approach like this:

1) Where this query builds a bunch of queries as a result set.

# =================
# VAR/CHAR SEARCH
# =================
# BE ADVISED USE ANY OF THESE WITH CAUTION
# DON'T RUN ON YOUR PRODUCTION SERVER 
# ** USE AN ALTERNATE BACKUP **

SELECT 
    CONCAT('SELECT * FROM ', A.TABLE_SCHEMA, '.', A.TABLE_NAME, 
           ' WHERE ', A.COLUMN_NAME, ' LIKE '%stuff%';') 
FROM INFORMATION_SCHEMA.COLUMNS A
WHERE 
            A.TABLE_SCHEMA != 'mysql' 
AND     A.TABLE_SCHEMA != 'innodb' 
AND     A.TABLE_SCHEMA != 'performance_schema' 
AND     A.TABLE_SCHEMA != 'information_schema'
AND     
        (
            A.DATA_TYPE LIKE '%text%'
        OR  
            A.DATA_TYPE LIKE '%char%'
        )
;

.

# =================
# NUMBER SEARCH
# =================
# BE ADVISED USE WITH CAUTION

SELECT 
    CONCAT('SELECT * FROM ', A.TABLE_SCHEMA, '.', A.TABLE_NAME, 
           ' WHERE ', A.COLUMN_NAME, ' IN ('%1234567890%');') 
FROM INFORMATION_SCHEMA.COLUMNS A
WHERE 
            A.TABLE_SCHEMA != 'mysql' 
AND     A.TABLE_SCHEMA != 'innodb' 
AND     A.TABLE_SCHEMA != 'performance_schema' 
AND     A.TABLE_SCHEMA != 'information_schema'
AND     A.DATA_TYPE IN ('bigint','int','smallint','tinyint','decimal','double')
;

.

# =================
# BLOB SEARCH
# =================
# BE ADVISED THIS IS CAN END HORRIFICALLY IF YOU DONT KNOW WHAT YOU ARE DOING
# YOU SHOULD KNOW IF YOU HAVE FULL TEXT INDEX ON OR NOT
# MISUSE AND YOU COULD CRASH A LARGE SERVER
SELECT 
    CONCAT('SELECT CONVERT(',A.COLUMN_NAME, ' USING utf8) FROM ', A.TABLE_SCHEMA, '.', A.TABLE_NAME, 
           ' WHERE CONVERT(',A.COLUMN_NAME, ' USING utf8) IN ('%someText%');') 
FROM INFORMATION_SCHEMA.COLUMNS A
WHERE 
            A.TABLE_SCHEMA != 'mysql' 
AND     A.TABLE_SCHEMA != 'innodb' 
AND     A.TABLE_SCHEMA != 'performance_schema' 
AND     A.TABLE_SCHEMA != 'information_schema'
AND     A.DATA_TYPE LIKE '%blob%'
;

Results should look like this:

Copy these results into another query window

2) You can then just Right Click and use the Copy Row (tab-separated)

enter image description here

3) Paste results in a new query window and run to your heart’s content.

Detail: I exclude system schema’s that you may not usually see in your workbench unless you have the option Show Metadata and Internal Schemas checked.

I did this to provide a quick way to ANALYZE an entire HOST or DB if needed or to run OPTIMIZE statements to support performance improvements.

I’m sure there are different ways you may go about doing this but here’s what works for me:

-- ========================================== DYNAMICALLY FIND TABLES AND CREATE A LIST OF QUERIES IN THE RESULTS TO ANALYZE THEM
SELECT CONCAT('ANALYZE TABLE ', TABLE_SCHEMA, '.', TABLE_NAME, ';') FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbname';

-- ========================================== DYNAMICALLY FIND TABLES AND CREATE A LIST OF QUERIES IN THE RESULTS TO OPTIMIZE THEM
SELECT CONCAT('OPTIMIZE TABLE ', TABLE_SCHEMA, '.', TABLE_NAME, ';') FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbname';

Tested On MySQL Version: 5.6.23

WARNING: DO NOT RUN THIS IF:

  1. You are concerned with causing Table-locks (keep an eye on your client-connections)
  2. You are unsure about what you are doing.

  3. You are trying to anger you DBA. (you may have people at your desk with the quickness.)

Cheers, Jay ;-]

Как происходит поиск в MySQL – руководство для начинающих

От автора: вы тут запись мою не видели? Выпала из базы, теперь не знаю, что и делать! Наверное, сегодня возьмемся за поиск в MySQL. А я как раз вспомню, как более эффективно просеивать данные в СУБД и заодно свою строку постараюсь найти.

Зачем просеивать?

Просеивание в MySQL – одна из самых часто выполняемых задач. Для этого в системах управления БД, поддерживающих SQL, используется команда SELECT. В предыдущих материалах мы уже сталкивались с ней, применяя ее для нахождения и вывода строк, отвечающих «простеньким» критериям сортировки. На самом деле данная команда является одной из главных, и ее возможности в сфере поиска записей почти безграничны.

При этом написание правильных запросов на выборку данных в MySQL очень часто похоже на составление заклинаний. Особенно такое впечатление складывается у новичков, которые только ступили на путь изучения СУБД. Но сегодня мы постараемся развеять это «сюрреалистическое» наваждение, и научимся составлять правильные запросы для поиска по MySQL базе.

Как уже у нас заведено, начнем с обзора возможностей phpMYAdmin. Посмотрим, каким встроенным функционалом для сортировки данных обладает эта программа.

Просеиваем строки через phpMyAdmin

Зайдите в программу, выберите любую БД и таблицу в ней. Я бы советовал вам использовать таблицу поменьше, в которой всего несколько срок. В них лучше видны результаты сортировки.

Профессия PHP-разработчик с нуля до PRO

Готовим PHP-разработчиков с нуля

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

Узнать подробнее

Командная стажировка под руководством тимлида

90 000 рублей средняя зарплата PHP-разработчика

3 проекта в портфолио для старта карьеры

Выбрав слева в меню базу и таблицу, перейдите сверху в раздел «Обзор». После этого СУБД выведет все строки, которые содержатся в данной структуре. Для этого программа направила на выполнение серверу БД запрос на выборку. Его код отображается выше результатов выборки.

Ниже находится весь встроенный функционал программы для поиска по MySQL базе. Чтобы установить способ «просеивания» по первичному ключу (по убыванию или возрастанию), используется переключатель «Сортировать по индексу».

Кроме этого можно «просеять» все строки, изменив порядок вывода данных по значению каждого из столбцов (убыванию и возрастанию). Для этого нужно нажать на имя столбца вверху списка. При этом для строковых значений порядок вывода будет изменяться в алфавитном порядке.

Но весь этот функционал пригодится вам только для осуществления поиска в небольших таблицах. Для более внушительных объемов данных придется использовать SQL.

Мощные средства SQL

Как уже упоминалось, для поиска в MySQL используется команда SELECT. Ее синтаксис я приводить не буду, поскольку его размер может испугать даже самого опытного разработчика. Поэтому только на скриншоте, чтобы вы не упали в обморок :).

Будет «постигать» данную команду на примерах ее использования, которые могут пригодиться вам для построения более сложных запросов. Стартуем! Я все-таки опять «поиграюсь» со своими «зверушками», и все запросы буду адресовать таблице animal:

Находим строку по номеру id:

SELECT * FROM `animal` WHERE id=1;

В этом запросе мы используем оператор WHERE, после которого задаем критерий поиска. Выводим определенные столбцы искомой строки:

SELECT name FROM `animal` WHERE id=1;

В данном примере мы вывели не полностью искомую строку, а только значение столбца name. Поиск по строковому значению:

SELECT * FROM `animal` WHERE name=‘gala’;

Здесь мы использовали в качестве параметра для поиска по MySQL базе строчное значение. Сортировка результатов выборки по возрастанию или убыванию:

SELECT * FROM  `animal` ORDER BY name;

Для сортировки результатов выборки мы использовали директиву ORDER BY. По умолчанию, установлена сортировка по возрастанию (ключевое слово ASC). Чтобы задать обратный порядок (по убыванию) нужно использовать слово DESC.

SELECT * FROM  `animal` ORDER BY name DESC;

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

SELECT * FROM `animal` WHERE name=‘dog’ ORDER BY ID DESC;

Углубляемся

Давайте покинем наше «зверье» и перенесемся в базу данных world. На ней я продемонстрирую еще несколько примеров выборки данных, соответствующих заданным параметрам. Все запросы я буду демонстрировать на основе таблицы country. Иногда (особенно в больших по размеру таблицах) требуется задать не один критерий для поиска, а несколько. Тогда запрос на получения списка стран из Европы и Африки будет выглядеть следующим образом:

SELECT Name, Continent FROM `country` WHERE Continent=‘Africa’ OR Continent=‘Europe’;

Этот же запрос на поиск по MySQL базе можно укоротить, если использовать ключевое слово in. Например:

SELECT Name, Continent FROM `country` WHERE Continent in (‘Africa’,‘Europe’);

Для указания диапазона выборки применяется ключевое слово Between. Давайте выведем страны с численностью населения от 10 до 50 тыс. За основу возьмем предыдущий запрос:

SELECT Name, Continent, Population FROM `country` WHERE Population BETWEEN 10000 and 50000;

Пример в PHP

Теперь приведем пример, как запустить поиск в PHP MySQL данных. Используем предыдущий запрос.

<?php

$load= mysqli_connect(‘localhost’, ‘root’, », ‘world’);

$res= mysqli_query($load, «SELECT Name,Continent,Population FROM `country` WHERE Population BETWEEN 10000 and 50000»);

$r=mysqli_fetch_assoc($res);

  while ($r = mysqli_fetch_assoc($res)) {

        printf(«%s (%s)n»,$r[«Name»],$r[«Continent»]);

    }

mysqli_free_result($res);

  mysqli_close($load);

?>

Профессия PHP-разработчик с нуля до PRO

Готовим PHP-разработчиков с нуля

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

Узнать подробнее

Командная стажировка под руководством тимлида

90 000 рублей средняя зарплата PHP-разработчика

3 проекта в портфолио для старта карьеры

Ну, вроде бы я вкратце рассказал вам все о поиске в MySQL. Надеюсь, из этой статьи вы почерпнули для себя что-то новенькое. А свою строку я так и не нашел. Наверное, кот утащил, пока я отходил от компа. Ох, уж это зверье :).

I’m trying to make a search feature that will search multiple columns to find a keyword based match. This query:

SELECT title FROM pages LIKE %$query%;

works only for searching one column, I noticed separating column names with commas results in an error. So is it possible to search multiple columns in mysql?

Quassnoi's user avatar

Quassnoi

411k91 gold badges612 silver badges612 bronze badges

asked Mar 25, 2010 at 10:08

George's user avatar

If it is just for searching then you may be able to use CONCATENATE_WS.
This would allow wild card searching.
There may be performance issues depending on the size of the table.

SELECT * 
FROM pages 
WHERE CONCAT_WS('', column1, column2, column3) LIKE '%keyword%'

bishop's user avatar

bishop

36.9k10 gold badges103 silver badges136 bronze badges

answered May 21, 2015 at 5:41

Terra Walker's user avatar

2

You can use the AND or OR operators, depending on what you want the search to return.

SELECT title FROM pages WHERE my_col LIKE %$param1% AND another_col LIKE %$param2%;

Both clauses have to match for a record to be returned. Alternatively:

SELECT title FROM pages WHERE my_col LIKE %$param1% OR another_col LIKE %$param2%;

If either clause matches then the record will be returned.

For more about what you can do with MySQL SELECT queries, try the documentation.

answered Mar 25, 2010 at 10:16

akamike's user avatar

akamikeakamike

2,13813 silver badges16 bronze badges

2

If your table is MyISAM:

SELECT  *
FROM    pages
WHERE   MATCH(title, content) AGAINST ('keyword' IN BOOLEAN MODE)

This will be much faster if you create a FULLTEXT index on your columns:

CREATE FULLTEXT INDEX fx_pages_title_content ON pages (title, content)

, but will work even without the index.

answered Mar 25, 2010 at 10:14

Quassnoi's user avatar

QuassnoiQuassnoi

411k91 gold badges612 silver badges612 bronze badges

2

1)

select *
from employee em
where CONCAT(em.firstname, ' ', em.lastname) like '%parth pa%';

2)

select *
from employee em
where CONCAT_ws('-', em.firstname, em.lastname) like '%parth-pa%';

First is usefull when we have data like : ‘firstname lastname’.

e.g

  • parth patel
  • parth p
  • patel parth

Second is usefull when we have data like : ‘firstname-lastname’. In it you can also use special characters.

e.g

  • parth-patel
  • parth_p
  • patel#parth

answered Nov 10, 2017 at 13:20

Parth Patel's user avatar

Parth PatelParth Patel

7991 gold badge13 silver badges20 bronze badges

Here is a query which you can use to search for anything in from your database as a search result ,

SELECT * FROM tbl_customer 
    WHERE CustomerName LIKE '%".$search."%'
    OR Address LIKE '%".$search."%' 
    OR City LIKE '%".$search."%' 
    OR PostalCode LIKE '%".$search."%' 
    OR Country LIKE '%".$search."%'

Using this code will help you search in for multiple columns easily

answered Jun 21, 2019 at 13:31

Ravi Khatri's user avatar

SELECT * FROM persons WHERE (`LastName` LIKE 'r%') OR (`FirstName` LIKE 'a%');

Please try with above query.

Mayank Vadiya's user avatar

answered Nov 9, 2016 at 5:52

user3781751's user avatar

Материал из Справочник Web-языков

Перейти к: навигация, поиск

Поиск записей осуществляется командой SELECT

SELECT * FROM table_name WHERE (выражение) [order by field_name [desc][asc]]

Эта команда ищет все записи в таблице table_name, которые удовлетворяют выражению выражение.

Если записей несколько, то при указанном предложении order by они будут отсортированы по тому полю, имя которого записывается правее этого ключевого слова (если задано слово desc, то упорядочивание происходит в обратном порядке). В предложении order by могут также задаваться несколько полей.

Особое значение имеет символ *. Он предписывает, что из отобранных записей следует извлечь все поля, когда будет выполнена команда получения выборки. С другой стороны, вместо звездочки можно через запятую непосредственно перечислить имена полей, которые требуют извлечения. Но чаще всего все же пользуются именно *.

Рассмотрим полный синтаксис оператора.

SELECT [STRAIGHT_JOIN]
       [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
       [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] [HIGH_PRIORITY]
       [DISTINCT | DISTINCTROW | ALL]
    expression,...
    [INTO {OUTFILE | DUMPFILE} 'file_name' export_options]
    [FROM table_references
      [WHERE where_definition]
      [GROUP BY {unsigned_integer | col_name | formula} [ASC | DESC], ...]
      [HAVING where_definition]
      [ORDER BY {unsigned_integer | col_name | formula} [ASC | DESC], ...]
      [LIMIT [offset,] rows]
      [PROCEDURE procedure_name]
      [FOR UPDATE | LOCK IN SHARE MODE]]

Все параметры, начинающиеся с SQL_, STRAIGHT_JOIN и HIGH_PRIORITY, представляют собой расширение MySQL для ANSI SQL. Опции DISTINCT, DISTINCTROW и ALL указывают, будут ли возвращаться дублирующиеся записи. По умолчанию установлен параметр (ALL), т.е. возвращаются все встречающиеся строки. DISTINCT и DISTINCTROW являются синонимами и указывают, что дублирующиеся строки в результирующем наборе данных должны быть удалены. Выражение expression задает столбцы, в которых необходимо проводить выборку.
Команда INTO OUTFILE ‘file_name’ осуществляет запись выбранных строк в файл, указанный в file_name. Данный файл создается на сервере и до этого не должен существовать. Для использования этой формы команды SELECT необходимы привилегии FILE. Если вместо INTO OUTFILE использовать INTO DUMPFILE, то MySQL запишет в файл только одну строку без символов завершения столбцов или строк и без какого бы то ни было экранирования. Следует учитывать, что любой файл, созданный с помощью INTO OUTFILE и INTO DUMPFILE, будет доступен для чтения всем пользователям.Выражение FROM table_references задает таблицы, из которых надлежит извлекать строки. Опция WHERE задает условия для выборки данных.

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

// Имя пользователя
$user="Admin";
// name - имя поля в таблице, которое содержит имена пользователей,
// оставивших свои сообщения в гостевой
// db_guest - имя таблицы, содержащей сообщения, оставленные в гостевой
$sql="select * from db_guest where (name='$user')";
$result=mysql_query($sql);
// Находим кол-во записей, удовлетворяющих условию
$rows=mysql_num_rows($result);
echo "$user оставил в гостевой $rows записей.";

Но что делать, если искомый текст не занимает все поле, а является частью этого поля (например, при поиске слова или словосочетания в общем массиве текста)?

Например я использую следующую команду (наверно этот способ не самый лучший, но тем не менее он работает):

// $search - содержит искомый тест
$sql="select * from db_guest where (locate('$search',content)>0)";
$result=mysql_query($sql);

Смысл такой: если кол-во вхождений строки $search в поле content больше 0 (т.е. оно вообще есть), то запись добавляется к остальным найденным записям.

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

// $search - содержит искомый тест
$sql="select * from db_guest where (locate(lower('$search'),lower(content))>0)";
$result=mysql_query($sql);

т.е. искомая строка и запись в таблице переводится в верхний регистр и затем производится поиск.

Теперь представим, что у нас есть база сообщений гостевой книги, и нам надо отсортировать сообщения по времени, когда они были оставлены.

Для этого одно из полей таблицы базы должно содержать время записи сообщения.

Сортировка по какому-либо столбцу осуществляется при помощи конструкции order by.

В нашем случае, при учете, что более «свежие» сообщения будут сортироваться верхними:

// time - столбец, содержащий время написания записи
// в формате "UNIX timestamp"
$sql="SELECT * FROM db_guest ORDER BY time DESC";
$result=mysql_query($sql);

Т.е. данные были отсортированны по убыванию.

Если нам надо отсортировать данные по возрастанию, надо вместо ключевого слова DESC применить ASC:

$sql="SELECT * FROM db_guest ORDER BY time ASC";
$result=mysql_query($sql);

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

$sql="SELECT * FROM db_name ORDER BY field1,field2 ASC";
$result=mysql_query($sql);

Сначало данные сортируются по первому столбцу field1. Затем, если в первом столбце есть несколько одинаковых значений, выполняется дополнительная сортировка по второму столбцу (внутри группы с одинаковыми значениями в первом столбце).

Если требуется, чтобы при поиске выдавались не все найденные записи, а определенная группа, то нужно использовать параметр LIMIT.

В этом параметре задается два значения:

LIMIT start,length
  • start — указывает, с какой позиции нужно выдавать найденные записи
  • length — кол-во записей

Например, нам нужно выбрать из базы данных гостевой книги записи начиная с 20 по 45 (т.е. чтоб вывести 25 записей):

$sql="select * from db_guest limit 20,25";
$result=mysql_query($sql);

Автор: RXL.
Дата написания: 3.12.2009.
Права на статью принадлежат автору и Клубу программистов «Весельчак У».

  • Вводная.
  • Информация о таблицах и столбцах.
  • Генерация SQL-кода.
  • Автоматизация выполнения.
  • Вдогонку.

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

MySQL предоставляет информацию об объектах баз данных через специальную схему «INFORMATION_SCHEMA». Например, так выглядит состав таблиц этой схемы в MySQL 5.0:

mysql> SHOW TABLES FROM information_schema;
+—————————————+
| Tables_in_information_schema          |
+—————————————+
| CHARACTER_SETS                        |
| COLLATIONS                            |
| COLLATION_CHARACTER_SET_APPLICABILITY |
| COLUMNS                               |
| COLUMN_PRIVILEGES                     |
| KEY_COLUMN_USAGE                      |
| PROFILING                             |
| ROUTINES                              |
| SCHEMATA                              |
| SCHEMA_PRIVILEGES                     |
| STATISTICS                            |
| TABLES                                |
| TABLE_CONSTRAINTS                     |
| TABLE_PRIVILEGES                      |
| TRIGGERS                              |
| USER_PRIVILEGES                       |
| VIEWS                                 |
+—————————————+
17 rows in set (0.00 sec)

Информация о колонках:

mysql> DESC information_schema.columns;
+—————————+—————+——+——+———+——-+
| Field                    | Type         | Null | Key | Default | Extra |
+—————————+—————+——+——+———+——-+
| TABLE_CATALOG            | varchar(512) | YES  |     | NULL    |       |
| TABLE_SCHEMA             | varchar(64)  | NO   |     |         |       |
| TABLE_NAME               | varchar(64)  | NO   |     |         |       |
| COLUMN_NAME              | varchar(64)  | NO   |     |         |       |
| ORDINAL_POSITION         | bigint(21)   | NO   |     | 0       |       |
| COLUMN_DEFAULT           | longtext     | YES  |     | NULL    |       |
| IS_NULLABLE              | varchar(3)   | NO   |     |         |       |
| DATA_TYPE                | varchar(64)  | NO   |     |         |       |
| CHARACTER_MAXIMUM_LENGTH | bigint(21)   | YES  |     | NULL    |       |
| CHARACTER_OCTET_LENGTH   | bigint(21)   | YES  |     | NULL    |       |
| NUMERIC_PRECISION        | bigint(21)   | YES  |     | NULL    |       |
| NUMERIC_SCALE            | bigint(21)   | YES  |     | NULL    |       |
| CHARACTER_SET_NAME       | varchar(64)  | YES  |     | NULL    |       |
| COLLATION_NAME           | varchar(64)  | YES  |     | NULL    |       |
| COLUMN_TYPE              | longtext     | NO   |     | NULL    |       |
| COLUMN_KEY               | varchar(3)   | NO   |     |         |       |
| EXTRA                    | varchar(20)  | NO   |     |         |       |
| PRIVILEGES               | varchar(80)  | NO   |     |         |       |
| COLUMN_COMMENT           | varchar(255) | NO   |     |         |       |
+—————————+—————+——+——+———+——-+
19 rows in set (0.00 sec)

Зачем я это рассказываю? Затем, что если вы будете писать руками SQL-запрос для каждой таблицы в схеме да еще и для каждого подходящего столбца — можно смело менять профессию, т.к. это точно не ваше. Нормальный человек найдет обобщенное решение, без тупого и бессмысленного труда. Это решение — создать необходимые запросы автоматически, и поможет нам в этом информация о таблицах и столбцах из таблицы «COLUMNS».

Нам нужно отобрать таблицы, в которых есть колонки подходящих для нас типов: CHAR, VARCHAR, TEXT и т.п. Всего 12 типов. Фильтровать будем по полю «DATA_TYPE». Такой запрос наглядно показывает типы столбцов в таблицах схемы «test»:

SELECT table_name, column_name, data_type
FROM information_schema.columns
WHERE table_schema = ‘test’
  AND data_type IN (
    ‘char’, ‘varchar’, ‘binary’, ‘varbinary’,
    ‘tinytext’, ‘text’, ‘mediumtext’, ‘longtext’,
    ‘tinyblob’, ‘blob’, ‘mediumblob’, ‘longblob’
  );

Если не на чем экспериментировать, воспользуйтесь этой таблицей:

CREATE TABLE `t2` (
  `f_vch` varchar(10) default NULL,
  `f_bin` varbinary(10) default NULL,
  `f_tblob` tinyblob,
  `f_blob` blob,
  `f_ttext` tinytext,
  `f_text` text,
  `f_ltext` longtext
);

Составим SQL-запрос, который создаст нам набор SQL-запросов для каждой таблицы указанной схемы.

SELECT CONCAT(
    ‘SELECT «‘, c.table_name, ‘» `$table$`’,
    ‘ FROM `’, c.table_schema, ‘`.`’, c.table_name, ‘`’
    ‘ WHERE ‘, GROUP_CONCAT(
      CONCAT(‘`’, c.column_name, ‘`’)
      SEPARATOR ‘ LIKE «%test%» OR ‘
    ), ‘ LIKE «%test%«‘,
    ‘ LIMIT 1’
  ) query
FROM information_schema.columns c
WHERE c.table_schema = ‘test’
  AND c.data_type IN (
    ‘char’, ‘varchar’, ‘binary’, ‘varbinary’,
    ‘tinytext’, ‘text’, ‘mediumtext’, ‘longtext’,
    ‘tinyblob’, ‘blob’, ‘mediumblob’, ‘longblob’
  )
GROUP BY c.table_name;

Например, у меня запрос вернул только одну строку для схемы «test»:

SELECT «t2» `$table$`
 FROM `test`.`t2`
 WHERE `f_vch` LIKE «%test%«
  OR `f_bin` LIKE «%test%«
  OR `f_tblob` LIKE «%test%«
  OR `f_blob` LIKE «%test%«
  OR `f_ttext` LIKE «%test%«
  OR `f_text` LIKE «%test%«
  OR `f_ltext` LIKE «%test%«
  OR `f_vbin` LIKE «%test%«
 LIMIT 1

Полученный запрос будет искать во всех текстовых полях вхождение строки «test» и остановится, найдя первую подходящую строку. Возможно, в него стоит добавить ORDER BY NULL для оптимизации под большие таблицы. Выводить саму строку я не стал — она может быть большой и неудобоваримой для просмотра в консоли. Тут уже дело вкуса — переделайте запрос, как вам захочется. Я вот переделал так:

SELECT CONCAT(
    ‘SELECT «‘, c.table_name, ‘» `$table$`, ‘, GROUP_CONCAT(
      CONCAT(‘SUM(IF(`’, c.column_name, ‘` LIKE «%test%«, 1, 0)) `’, c.column_name, ‘`’)
      SEPARATOR ‘, ‘
    ),
    ‘ FROM `’, c.table_schema, ‘`.`’, c.table_name, ‘`’
    ‘ WHERE ‘, GROUP_CONCAT(
      CONCAT(‘`’, c.column_name, ‘` LIKE «%test%«‘)
      SEPARATOR ‘ OR ‘
    )
  ) query
FROM information_schema.columns c
WHERE c.table_schema = ‘test’
  AND c.data_type IN (
    ‘char’, ‘varchar’, ‘binary’, ‘varbinary’,
    ‘tinytext’, ‘text’, ‘mediumtext’, ‘longtext’,
    ‘tinyblob’, ‘blob’, ‘mediumblob’, ‘longblob’
  )
GROUP BY c.table_name;

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

mysql> SELECT «t2» `$table$`,
  SUM(IF(`f_vch` LIKE «%test%», 1, 0)) `f_vch`,
  SUM(IF(`f_bin` LIKE «%test%», 1, 0)) `f_bin`,
  SUM(IF(`f_tblob` LIKE «%test%», 1, 0)) `f_tblob`,
  SUM(IF(`f_blob` LIKE «%test%», 1, 0)) `f_blob`,
  SUM(IF(`f_ttext` LIKE «%test%», 1, 0)) `f_ttext`,
  SUM(IF(`f_text` LIKE «%test%», 1, 0)) `f_text`,
  SUM(IF(`f_ltext` LIKE «%test%», 1, 0)) `f_ltext`,
  SUM(IF(`f_vbin` LIKE «%test%», 1, 0)) `f_vbin`
 FROM `test`.`t2`
 WHERE `f_vch` LIKE «%test%»
  OR `f_bin` LIKE «%test%»
  OR `f_tblob` LIKE «%test%»
  OR `f_blob` LIKE «%test%»
  OR `f_ttext` LIKE «%test%»
  OR `f_text` LIKE «%test%»
  OR `f_ltext` LIKE «%test%»
  OR `f_vbin` LIKE «%test%»;
+———+——-+——-+———+———+———+———+———+———+
| $table$ | f_vch | f_bin | f_tblob | f_blob | f_ttext | f_text | f_ltext | f_vbin |
+———+——-+——-+———+———+———+———+———+———+
| t2      |     1 |     0 |       0 |      0 |       0 |      0 |       0 |      0 |
+———+——-+——-+———+———+———+———+———+———+
1 row in set (0.00 sec)

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

Заметьте, что искомый текст я вставлял непосредственно в запрос. Это ограничение агрегатной функции GROUP_CONCAT — она допускает только константную строку в качестве разделителя — переменную туда подставить не удастся. (Данное ограничение позже решилось выносом подстановки искомой строки из SEPARATOR в группируемое выражение.)

Для решения этой проблемы в процедуре я делаю подстановку функцией REPLACE в уже готовом запросе. Искомую строку стоит предварительно обработать для экранирования недопустимых символов, чтобы не было неприятных сбоев. Здесь я сделал лишь замену одинарной кавычки на обратный слеш и кавычку, но правильнее будет обработать искомую строку функцией QUOTE и удалить из результата первый и последний символ (это тоже одинарные кавычки — их подставляет QUOTE).

Готовый и протестированный код процедуры:

DROP PROCEDURE IF EXISTS find_overall;
delimiter $$
CREATE PROCEDURE find_overall(
  p_dbname VARCHAR(64),
  p_search VARCHAR(255)
)
BEGIN
  DECLARE query TEXT;
  DECLARE eof BOOL;
  DECLARE curs_tables CURSOR FOR
    SELECT CONCAT(
        ‘SELECT «‘, c.table_name, ‘» `$table$`, ‘, GROUP_CONCAT(
          CONCAT(
            ‘SUM(IF(`’, c.column_name, ‘` LIKE «%%«, 1, 0))’,
            ‘ `’, c.column_name, ‘`’
          )
          SEPARATOR ‘, ‘
        ),
        ‘ FROM `’, c.table_schema, ‘`.`’, c.table_name, ‘`’
        ‘ WHERE ‘, GROUP_CONCAT(
          CONCAT(‘`’, c.column_name, ‘`’)
          SEPARATOR ‘ LIKE «%%» OR ‘
        ), ‘ LIKE «%%«‘
      ) query
    FROM information_schema.columns c
    WHERE c.table_schema = p_dbname
      AND c.data_type IN (
        ‘char’, ‘varchar’, ‘binary’, ‘varbinary’,
        ‘tinytext’, ‘text’, ‘mediumtext’, ‘longtext’,
        ‘tinyblob’, ‘blob’, ‘mediumblob’, ‘longblob’
      )
    GROUP BY c.table_name;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET eof = TRUE;

  OPEN curs_tables;
  SET eof = FALSE;

  L_tables: LOOP
    FETCH curs_tables INTO query;

    IF eof THEN LEAVE L_tables; END IF;

    SET @stm = REPLACE(query, ‘»%%«‘,
      CONCAT(‘»%, REPLACE(p_search, «‘», «\‘») , %«‘)
    );
    PREPARE find_overall FROM @stm;
    EXECUTE find_overall;
    DROP PREPARE find_overall;
  END LOOP;

  CLOSE curs_tables;
END;$$
delimiter ;

Смотрите, разбирайтесь. Потенциально данный код не защищен от SQL-injection, но и назначение у него чисто административное.

Вопросы можно задать на нашем форуме. Статья писалась быстро и, возможно что-то, стоит переделать или добавить — буду раз замечаниям и предложениям.


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

DROP PROCEDURE IF EXISTS find_overall;
delimiter $$
CREATE PROCEDURE find_overall(
  p_dbname VARCHAR(64),
  p_search VARCHAR(255)
)
BEGIN
  DECLARE search_string VARCHAR(512);
  DECLARE table_name VARCHAR(64);
  DECLARE column_name VARCHAR(64);
  DECLARE selections TEXT;
  DECLARE conditions TEXT;
  DECLARE eof BOOL;
  DECLARE curs_tables CURSOR FOR
    SELECT DISTINCT c.table_name
    FROM information_schema.columns c
    WHERE c.table_schema = p_dbname
      AND c.data_type IN (
        ‘char’, ‘varchar’, ‘binary’, ‘varbinary’,
        ‘tinytext’, ‘text’, ‘mediumtext’, ‘longtext’,
        ‘tinyblob’, ‘blob’, ‘mediumblob’, ‘longblob’
      );
  DECLARE curs_columns CURSOR FOR
    SELECT c.column_name
    FROM information_schema.columns c
    WHERE c.table_schema = p_dbname
      AND c.table_name = table_name
      AND c.data_type IN (
        ‘char’, ‘varchar’, ‘binary’, ‘varbinary’,
        ‘tinytext’, ‘text’, ‘mediumtext’, ‘longtext’,
        ‘tinyblob’, ‘blob’, ‘mediumblob’, ‘longblob’
      );
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET eof = TRUE;

  SET search_string = QUOTE(p_search);
  SET search_string = SUBSTR(search_string, 2, LENGTH(search_string) 2);

  OPEN curs_tables;
  SET eof = FALSE;

  L_tables: LOOP
    FETCH curs_tables INTO table_name;

    IF eof THEN LEAVE L_tables; END IF;

    OPEN curs_columns;
    SET selections = »;
    SET conditions = »;

    L_columns: LOOP
      FETCH curs_columns INTO column_name;

      IF eof THEN LEAVE L_columns; END IF;

      SET selections = CONCAT(selections,
        IF(selections = », », ‘, ‘),
        ‘SUM(IF(`’, column_name, ‘` LIKE «%, search_string, %«, 1, 0))’,
        ‘ `’, column_name, ‘`’
      );
      SET conditions = CONCAT(conditions,
        IF(conditions = », », ‘ OR ‘),
        ‘`’, column_name, ‘` LIKE «%, search_string, %«‘
      );
    END LOOP;

    CLOSE curs_columns;
    SET eof = FALSE;

    SET @stm = CONCAT(
      ‘SELECT «‘, table_name, ‘» `$table$`, ‘, selections,
      ‘ FROM `’, p_dbname, ‘`.`’, table_name, ‘`’,
      ‘ WHERE ‘, conditions
    );
    PREPARE find_overall FROM @stm;
    EXECUTE find_overall;
    DROP PREPARE find_overall;
  END LOOP;

  CLOSE curs_tables;
END;$$
delimiter ;

Быстродействие проверено на схеме с 62-я таблицам MYISAM общим объемом 148 МБ (только файлы MYD), на сервере с двумя одноядерными Xeon 2.8 ГГц и 3 ГБ DDR1 ECC.

Query OK, 0 rows affected (3.07 sec)

Повторный вызов отрабатывает за 2.58 секунды.

Следующую модификацию процедуры find_overall не рекомендую запускать в консоли. Он вернет множество рекордсетов — по одному на каждую проверяемую таблицу.

DROP PROCEDURE IF EXISTS find_overall;
delimiter $$
CREATE PROCEDURE find_overall(
  p_dbname VARCHAR(64),
  p_search VARCHAR(255)
)
BEGIN
  DECLARE search_string VARCHAR(512);
  DECLARE table_name VARCHAR(64);
  DECLARE column_name VARCHAR(64);
  DECLARE selections TEXT;
  DECLARE conditions TEXT;
  DECLARE eof BOOL;
  DECLARE curs_tables CURSOR FOR
    SELECT DISTINCT c.table_name
    FROM information_schema.columns c
    WHERE c.table_schema = p_dbname
      AND c.data_type IN (
        ‘char’, ‘varchar’, ‘binary’, ‘varbinary’,
        ‘tinytext’, ‘text’, ‘mediumtext’, ‘longtext’,
        ‘tinyblob’, ‘blob’, ‘mediumblob’, ‘longblob’
      );
  DECLARE curs_columns CURSOR FOR
    SELECT c.column_name
    FROM information_schema.columns c
    WHERE c.table_schema = p_dbname
      AND c.table_name = table_name
      AND c.data_type IN (
        ‘char’, ‘varchar’, ‘binary’, ‘varbinary’,
        ‘tinytext’, ‘text’, ‘mediumtext’, ‘longtext’,
        ‘tinyblob’, ‘blob’, ‘mediumblob’, ‘longblob’
      );
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET eof = TRUE;

  SET search_string = QUOTE(p_search);
  SET search_string = SUBSTR(search_string, 2, LENGTH(search_string) 2);

  OPEN curs_tables;
  SET eof = FALSE;

  L_tables: LOOP
    FETCH curs_tables INTO table_name;

    IF eof THEN LEAVE L_tables; END IF;

    OPEN curs_columns;
    SET selections = »;
    SET conditions = »;

    L_columns: LOOP
      FETCH curs_columns INTO column_name;

      IF eof THEN LEAVE L_columns; END IF;

      SET selections = CONCAT(selections,
        IF(selections = », », ‘, ‘),
        ‘IF(`’, column_name, ‘` LIKE «%, search_string, %«, `’, column_name, ‘`, NULL)’,
        ‘ `’, column_name, ‘`’
      );
      SET conditions = CONCAT(conditions,
        IF(conditions = », », ‘ OR ‘),
        ‘`’, column_name, ‘` LIKE «%, search_string, %«‘
      );
    END LOOP;

    CLOSE curs_columns;
    SET eof = FALSE;

    SET @stm = CONCAT(
      ‘SELECT «‘, table_name, ‘» `$table$`, ‘, selections,
      ‘ FROM `’, p_dbname, ‘`.`’, table_name, ‘`’,
      ‘ WHERE ‘, conditions
    );
    PREPARE find_overall FROM @stm;
    EXECUTE find_overall;
    DROP PREPARE find_overall;
  END LOOP;

  CLOSE curs_tables;
END;$$
delimiter ;

Понравилась статья? Поделить с друзьями:

Не пропустите также:

  • Как найти силу тока проходящего через резистор
  • Как найти внешние углы доказать
  • Как найти след основателя в джунглях
  • Как правильно составить расписку что претензий не имею
  • Как найти землю тестером

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии