在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 @ARC_CHECKNUM VARCHAR(MAX)
SET @ARC_CHECKNUM = 'ABC,135,MED,ASFSDFSF,AXX'
SELECT ' AND (a.arc_checknum LIKE ''%' + REPLACE(@arc_checknum,',','%'' OR a.arc_checknum LIKE ''%') + '%'')''

评估:

 AND (a.arc_checknum LIKE '%ABC%' OR a.arc_checknum LIKE '%135%' OR a.arc_checknum LIKE '%MED%' OR a.arc_checknum LIKE '%ASFSDFSF%' OR a.arc_checknum LIKE '%AXX%')

如果希望它使用索引,则必须省略第一个'%'字符。

其他回答

我有一个简单的解决方案,至少在postgresql中工作,使用like any后跟regex列表。这里有一个例子,看看在清单中识别一些抗生素:

select *
from database.table
where lower(drug_name) like any ('{%cillin%,%cyclin%,%xacin%,%mycine%,%cephal%}')

您可以以牺牲性能为代价,为大量元素动态地执行此操作,但这是可行的。

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;

另一个解决方案,应该适用于任何RDBMS:

WHERE EXISTS (SELECT 1
                FROM (SELECT 'bla%' pattern FROM dual UNION ALL
                      SELECT '%foo%'        FROM dual UNION ALL
                      SELECT 'batz%'        FROM dual)
               WHERE something LIKE pattern)

内部选择可以用另一个模式源替换,比如表(或视图),如下所示:

WHERE EXISTS (SELECT 1
                FROM table_of_patterns t
               WHERE something LIKE t.pattern)

Table_of_patterns应该至少包含一个列模式,可以像这样填充:

INSERT INTO table_of_patterns(pattern) VALUES ('bla%');
INSERT INTO table_of_patterns(pattern) VALUES ('%foo%');
INSERT INTO table_of_patterns(pattern) VALUES ('batz%');

你被困在

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

除非你填充一个临时表(包括数据中的通配符)并像这样连接:

FROM YourTable                y
    INNER JOIN YourTempTable  t On y.something LIKE t.something

试试(使用SQL Server语法):

declare @x table (x varchar(10))
declare @y table (y varchar(10))

insert @x values ('abcdefg')
insert @x values ('abc')
insert @x values ('mnop')

insert @y values ('%abc%')
insert @y values ('%b%')

select distinct *
FROM @x x
WHERE x.x LIKE '%abc%' 
   or x.x LIKE '%b%'


select distinct x.*  
FROM @x             x
    INNER JOIN  @y  y On x.x LIKE y.y

输出:

x
----------
abcdefg
abc

(2 row(s) affected)

x
----------
abc
abcdefg

(2 row(s) affected)

在SQL SERVER中使用游标并执行每一个值:

表样例:

 create table Gastos_ConciliacionExcluida(IdRegistro int identity(1,1), MascaraTexto nvarchar(50), Activa bit default 1, Primary key (IDRegistro))


insert into Gastos_ConciliacionExcluida(MascaraTexto) Values ('%Reembolso%')



alter procedure SP_Gastos_ConciliacionExcluidaProcesar
as

declare cur cursor for select MascaraTexto From Gastos_ConciliacionExcluida where Activa=1
declare @Txt nvarchar(50)

open cur

fetch next from cur into @Txt
while @@Fetch_Status = 0
begin
    update Gastos_BancoRegistro set PresumibleNoConciliable = 1 
    where   Concepto like @txt
    fetch next from cur into @Txt
end 
close cur
deallocate cur