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), ...)

区别在于,它在指定的值中搜索列的选择,而我正在尝试在单个值中搜索所有列。

但这并不重要,就像我说的多于我只是好奇

Answers:


23

SQL不能提供一种很好的方法来执行此操作,因为拥有N个列的值可能在同一域中可能不是一个好的表设计。这是潜在的“重复组”一样,如果你有列的情况下phone1phone2phone3,... 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 like(假设您的表在模式S中被命名为T:

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');

现在,您可以执行此字符串。请注意,您必须用额外的引号引起来。例如,如果将其放入过程中,则可以准备并执行所生成的字符串。

我测试了:

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中,可以右键单击表或架构,然后选择“搜索表数据”。模式上下文菜单


0

试试这个:

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

这假定.您的搜索字符串中没有。如果不能保证,则可以使用其他“分隔符”。


1
您能否解释为什么您的解决方案有效?在这里,仅代码答案不被视为一个好答案。
George.Palacios

它不起作用。例如,如果te搜索包含%_或任何列包含.
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');

如果所有列中都存在“值”,则仅返回一行。


1
你是说if 'value' is present in any of the columns吗 此外,您可以为以下字符串类型添加谓词:`和DATA_TYPE IN('char','varchar')`
Lennart

1
这样便可以实现OP的目标,即避免显式命名列。它不是通配符,但是针对信息模式的GROUP_CONCAT与所有列名的通配符一样好。
tbrookside

2
我无法使它正常工作。我用架构和表名替换了db和table,还有其他打算用作实际名称的占位符吗?另外,我自己尝试了内部语句,并且意识到它可以CONCAT列名,而不是行数据。那是你打算的吗?
donutguy640

4
出于所有应有的尊重,这是错误的。您的查询会将“值”与列进行比较,而不是它们的内容。我必须对此表示反对。
Bill Karwin19年

4
更准确地说,这会将字符串“值”与作为逗号分隔的列名称列表的字符串进行比较-与基本上相同where 'value' in ('col1,col2,col3…')
Andriy M
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.