在SQL I中(很遗憾)经常不得不使用“LIKE”条件,因为数据库违反了几乎所有的规范化规则。我现在改变不了。但这与问题无关。

此外,我经常使用诸如WHERE(1,1,2,3,5,8,13,21)中的某些内容之类的条件,以提高SQL语句的可读性和灵活性。

有没有可能在不编写复杂的子选择的情况下将这两者结合起来?

我想要一些像WHERE一样简单的东西('bla%', '%foo%', 'batz%')而不是这样:

WHERE something LIKE 'bla%'
OR something LIKE '%foo%'
OR something LIKE 'batz%'

我在这里与SQl Server和Oracle一起工作,但我感兴趣的是,这是否可能在任何RDBMS中。


当前回答

很抱歉挖出了一个旧帖子,但它有很多观点。这周我遇到了一个类似的问题,我想到了这个模式:

declare @example table ( sampletext varchar( 50 ) );

insert @example values 
( 'The quick brown fox jumped over the lazy dog.' ),
( 'Ask not what your country can do for you.' ),
( 'Cupcakes are the new hotness.' );

declare @filter table ( searchtext varchar( 50 ) );

insert @filter values
( 'lazy' ),
( 'hotness' ),
( 'cupcakes' );

-- Expect to get rows 1 and 3, but no duplication from Cupcakes and Hotness
select * 
from @example e
where exists ( select * from @filter f where e.sampletext like '%' + searchtext + '%' )

Exists()比join()工作得稍微好一点,因为它只测试集合中的每个记录,但如果有多个匹配则不会导致重复。

其他回答

这可以在Postgres中使用like或ilike以及any或all with array实现。这是我使用Postgres 9的一个例子:

select id, name from tb_organisation where name ilike any (array['%wembley%', '%south%']);

然后打印出来:

 id  |          name
-----+------------------------
 433 | South Tampa Center
 613 | South Pole
 365 | Bromley South
 796 | Wembley Special Events
 202 | Southall
 111 | Wembley Inner Space

在SQL中没有LIKE和IN的组合,更不用说TSQL (SQL Server)或PLSQL (Oracle)了。部分原因是全文检索(FTS)是推荐的替代方法。

Oracle和SQL Server的FTS实现都支持CONTAINS关键字,但语法仍然略有不同:

Oracle:

WHERE CONTAINS(t.something, 'bla OR foo OR batz', 1) > 0

SQL服务器:

WHERE CONTAINS(t.something, '"bla*" OR "foo*" OR "batz*"')

要查询的列必须是全文索引的。

参考:

使用Oracle文本构建全文搜索应用程序 理解SQL Server全文

PostgreSQL有ANY或ALL表单:

WHERE col LIKE ANY( subselect )

or

WHERE col LIKE ALL( subselect )

其中子选择只返回一列数据。

我在这里与SQl Server和Oracle一起工作,但我感兴趣的是,这是否可能在任何RDBMS中。

Teradata支持LIKE ALL/ANY语法:

ALL every string in the list. ANY any string in the list. ┌──────────────────────────────┬────────────────────────────────────┐ │ THIS expression … │ IS equivalent to this expression … │ ├──────────────────────────────┼────────────────────────────────────┤ │ x LIKE ALL ('A%','%B','%C%') │ x LIKE 'A%' │ │ │ AND x LIKE '%B' │ │ │ AND x LIKE '%C%' │ │ │ │ │ x LIKE ANY ('A%','%B','%C%') │ x LIKE 'A%' │ │ │ OR x LIKE '%B' │ │ │ OR x LIKE '%C%' │ └──────────────────────────────┴────────────────────────────────────┘


编辑:

jOOQ 3.12.0版本支持该语法:

添加合成[NOT]像任何和[NOT]像所有操作符

很多时候,SQL用户希望能够组合like和IN谓词,例如: SELECT * 从客户 WHERE last_name [NOT] LIKE ANY ('A%', 'E%') [ESCAPE '!'] 解决方法是手动将谓词展开为等效谓词 SELECT * 从客户 WHERE last_name LIKE 'A%' 或last_name LIKE 'E%' jOOQ可以开箱即用地支持这样一个合成谓词。


LIKE/ILIKE ANY(数组[]):

SELECT *
FROM t
WHERE c LIKE ANY (ARRAY['A%', '%B']);

SELECT *
FROM t
WHERE c LIKE ANY ('{"Do%", "%at"}');

db < > fiddle演示


雪花也支持LIKE ANY/LIKE ALL匹配:

像任何/所有 允许基于与一个或多个模式比较的字符串进行区分大小写的匹配。 <subject> LIKE ANY (<pattern1> [, <pattern2>…) [ESCAPE <escape_char>]

例子:

SELECT * 
FROM like_example 
WHERE subject LIKE ANY ('%Jo%oe%','T%e')
-- WHERE subject LIKE ALL ('%Jo%oe%','J%e')

从2016年开始,SQL Server包含了一个STRING_SPLIT函数。我使用SQL Server v17.4,我得到了这为我工作:

DECLARE @dashboard nvarchar(50)
SET @dashboard = 'P1%,P7%'

SELECT * from Project p
JOIN STRING_SPLIT(@dashboard, ',') AS sp ON p.ProjectNumber LIKE sp.value