在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 @val nvarchar(256),
@list nvarchar(max) = 'one,two,three,ten,five';
CREATE table #table (FIRST_NAME nvarchar(512), LAST_NAME nvarchar(512));
CREATE table #student (FIRST_NAME nvarchar(512), LAST_NAME nvarchar(512), EMAIL
nvarchar(512));
INSERT INTO #student (FIRST_NAME, LAST_NAME, EMAIL)
SELECT 'TEST', ' redOne' ,'test.redOne@toto.com' UNION ALL
SELECT 'student', ' student' ,'student@toto.com' UNION ALL
SELECT 'student', ' two' ,'student.two@toto.com' UNION ALL
SELECT 'hello', ' ONE TWO THREE' ,'student.two@toto.com'
DECLARE check_cursor CURSOR FOR select value from STRING_SPLIT(@list,',')
OPEN check_cursor
FETCH NEXT FROM check_cursor INTO @val
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @val
IF EXISTS (select * from #student where REPLACE(FIRST_NAME, ' ','')
like '%' + @val + '%' OR REPLACE(LAST_NAME, ' ','') like '%' + @val + '%')
BEGIN
INSERT INTO #table (FIRST_NAME, LAST_NAME )
SELECT TOP 1 FIRST_NAME, LAST_NAME VALUE from #student where
REPLACE(FIRST_NAME, ' ','') like '%' + @val + '%' OR REPLACE(LAST_NAME, ' ','')
like '%' + @val + '%'
END;
FETCH NEXT FROM check_cursor INTO @val
END
CLOSE check_cursor;
DEALLOCATE check_cursor;
SELECT * FROM #table;
DROP TABLE #table;
DROP TABLE #student;
如果您希望语句易于阅读,那么可以使用REGEXP_LIKE(从Oracle版本10开始可用)。
一个示例表:
SQL> create table mytable (something)
2 as
3 select 'blabla' from dual union all
4 select 'notbla' from dual union all
5 select 'ofooof' from dual union all
6 select 'ofofof' from dual union all
7 select 'batzzz' from dual
8 /
Table created.
原始语法:
SQL> select something
2 from mytable
3 where something like 'bla%'
4 or something like '%foo%'
5 or something like 'batz%'
6 /
SOMETH
------
blabla
ofooof
batzzz
3 rows selected.
以及一个使用REGEXP_LIKE的简单查询
SQL> select something
2 from mytable
3 where regexp_like (something,'^bla|foo|^batz')
4 /
SOMETH
------
blabla
ofooof
batzzz
3 rows selected.
但是…
我自己不会推荐它,因为它的性能不太好。我将坚持使用几个LIKE谓词。这些例子只是为了好玩。
我在这里与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')