MySQL - Как проверить значение во всех столбцах


11

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

Я хотел бы включить это:

SELECT * FROM table WHERE col1 = 'val' OR col2 = 'val' OR col3 = 'val';

в это:

SELECT * FROM table WHERE * = 'val'

... или даже лучше (хотя я в этом серьезно сомневаюсь ...)

SELECT * FROM table WHERE * like '%val%'

Я нашел это , что кажется довольно-таки не очень близким, но я не нахожу ничего более близкого:

SELECT whatever WHERE col1,col2 IN ((val1, val2), (val1, val2), ...)

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

Это не важно, хотя, как я сказал больше всего, мне просто любопытно

Ответы:


23

SQL не обеспечивает хороший способ сделать это, потому что, вероятно, не очень хороший дизайн таблицы, когда N столбцов могут иметь значения в одном домене. Это потенциально случай «повторяющихся групп» , как если у вас есть столбцы phone1, phone2, phone3, ... phoneN.

Если у вас есть несколько столбцов с одинаковым логическим доменом значений, это может быть случай, когда это многозначный атрибут (как в примере с телефонами). Стандартный способ хранения многозначных атрибутов - это создание нескольких строк в другой таблице со ссылкой на строку, которой они принадлежат в первичной таблице.

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

SELECT t.* FROM mytable AS t
JOIN phones AS p ON t.primaryKey = p.refKey 
WHERE p.phone = ?

1
И если по какой-либо причине вы не можете изменить макет таблицы, вы можете написать представление, представляющее данные в этом формате, а затем запросить представление.
CodeCaster

10
Нет, просто измените раскладку стола. Вот и все. Я устал от оправдания "Я не могу это изменить". Я больше не принимаю это. Пришло время научиться что-то менять.
Билл Карвин

15

Чем ближе вы можете получить это, используя IN:

SELECT * FROM table WHERE 'val' IN (col1, col2, ..., colN) ;

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


3

Вам нужно сделать это в два шага, сначала сгенерировать sql-подобие (при условии, что ваша таблица имеет имя T в схеме S:

select concat(' SELECT * FROM t WHERE ''a'' in ('
             , GROUP_CONCAT(COLUMN_NAME)
             , ')')
from INFORMATION_SCHEMA.columns 
where table_schema = 's' 
  and table_name = 't'
  and DATA_TYPE IN ('char','varchar');

Теперь вы можете выполнить эту строку. Обратите внимание, что вы должны заключать в кавычки 'a' с дополнительным. Если вы вставите это, например, в процедуру, вы можете подготовить и выполнить сгенерированную строку.

Я проверил с:

create table t (a char(3), b varchar(5), c int);
insert into t(a,b) values ('a','b'),('b','c'),('c','c');    

Запрос генерируется где:

SELECT * FROM t WHERE 'a' in (a,b)

и выполнение этого приводит к:

a   b   c
---------
a   b   

1

Кажется, прошел год с тех пор, как я спросил об этом, но я просто наткнулся на то, что, кажется, именно то, что я искал! Это не оператор SQL, как я ожидал, но он делает то, что я хотел.

В MySQL Workbench вы можете щелкнуть правой кнопкой мыши таблицу или схему и выбрать Search Table Data.контекстное меню схемы


0

Попробуй это:

select
    *
from
    _table_
where
    concat('.', col1, '.', col2, '.', col3, '.') like "%.search_value.%";

Это предполагает, что нет .в вашей строке поиска. Если вы не можете гарантировать это, возможно, вы можете использовать другой «символ-разделитель».


1
Не могли бы вы объяснить, почему ваше решение работает, пожалуйста? Ответы только кода не рассматриваются как хороший ответ здесь.
Джордж. Паласиос

это не работает Например, если поиск содержит %или _любой столбец содержит.
Jasen

1
@Jasen Вы можете экранировать специальные символы и использовать другой разделитель.
Anon0012398193

@ George.Palacios - что ты находишь неясным?
Anon0012398193

Выбор правильного разделителя может быть очень сложным. этот подход очень трудно сделать правильно
Jasen

0

Самое простое решение делает

mysqldump ... --skip-extended-insert db table | grep 'val'

Если только val не является обычным явлением в синтаксисе sql.


Я надеюсь, что вы издеваетесь надо мной, так как альтернатива в том, что вы думали, что это будет полезно.
donutguy640

1
Я определенно нет. Это правильный способ найти что-то, если вы не знаете, «где» это находится в таблице базы данных. Grep вернет все строки (включая имя таблицы), где присутствует значение. Это не SQL и не очень полезно, если вы хотите обработать вывод программно, но это просто и довольно быстро.
jkavalik

-2

Попробуй это.

SELECT *
FROM table
WHERE CONCAT(col1,' ',col2,' ',col3)="val val val";

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


-3

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

select * from db.table where 'value' in (select GROUP_CONCAT(COLUMN_NAME) from INFORMATION_SCHEMA.columns where table_schema = 'db' and table_name = 'table');

Это вернет строку, только если 'value' присутствует во всех столбцах.


1
Вы имеете в виду if 'value' is present in any of the columns? Кроме того, вы можете добавить предикат для строковых типов, таких как: `и DATA_TYPE IN ('char', 'varchar')`
Леннарт

1
Это сделает это и достигнет цели OP - избежать явного именования столбцов. Это не подстановочный знак, но GROUP_CONCAT для информационной схемы так же хорош, как подстановочный знак для всех имен столбцов.
tbrookside

2
У меня проблемы с тем, чтобы заставить это работать. Я заменил db и table моими схемами и именами таблиц. Есть ли что-то еще, предназначенное для заполнения реальных имен? Кроме того, я попробовал внутреннее утверждение самостоятельно и осознаю, что оно КОНКАТИРУЕТ имена столбцов, а не данные строк. Это то, что вы намеревались?
donutguy640

4
При всем уважении, это неправильно. Ваш запрос будет сравнивать «значение» с именами столбцов, а не с их содержимым . Я должен дать этому отрицательное голосование.
Билл Карвин

4
Точнее, при этом строка 'value' будет сравниваться со строкой, представляющей собой список имен столбцов через запятую, по сути, такой же, как where 'value' in ('col1,col2,col3…').
Андрей М
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.