在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中。
在T-SQL中,这个选项是有效的,但不是很快:
CREATE FUNCTION FN_LIKE_IN (@PROC NVARCHAR(MAX), @ITENS NVARCHAR(MAX)) RETURNS NVARCHAR(MAX) AS BEGIN
--Search an item with LIKE inside a list delimited by "," Vathaire 11/06/2019
DECLARE @ITEM NVARCHAR(MAX)
WHILE CHARINDEX(',', @ITENS) > 0 BEGIN
SET @ITEM = LEFT(@ITENS, CHARINDEX(',', @ITENS) - 1)
--IF @ITEM LIKE @PROC
IF @PROC LIKE @ITEM
RETURN @PROC --@ITEM --1
ELSE
SET @ITENS = STUFF(@ITENS, 1, LEN(@ITEM) + 1, '')
END
IF @PROC LIKE @ITENS RETURN @PROC --@ITEM --1
RETURN NULL --0
END
查询:
SELECT * FROM SYS.PROCEDURES
WHERE DBO.FN_LIKE_IN(NAME, 'PRC%,SP%') IS NOT NULL
如果您想封装上面所示的Inner Join或临时表技术,我建议使用TableValue用户函数。这样可以看得更清楚一点。
在使用定义在:http://www.logiclabz.com/sql-server/split-function-in-sql-server-to-break-comma-separated-strings-into-table.aspx的split函数后
我们可以根据我创建的名为“Fish”的表编写以下内容(int id, varchar(50) Name)
SELECT Fish.* from Fish
JOIN dbo.Split('%ass,%e%',',') as Splits
on Name like Splits.items //items is the name of the output column from the split function.
输出
1 Bass
2 Pike
7 Angler
8 Walleye
你甚至可以试试这个
函数
CREATE FUNCTION [dbo].[fn_Split](@text varchar(8000), @delimiter varchar(20))
RETURNS @Strings TABLE
(
position int IDENTITY PRIMARY KEY,
value varchar(8000)
)
AS
BEGIN
DECLARE @index int
SET @index = -1
WHILE (LEN(@text) > 0)
BEGIN
SET @index = CHARINDEX(@delimiter , @text)
IF (@index = 0) AND (LEN(@text) > 0)
BEGIN
INSERT INTO @Strings VALUES (@text)
BREAK
END
IF (@index > 1)
BEGIN
INSERT INTO @Strings VALUES (LEFT(@text, @index - 1))
SET @text = RIGHT(@text, (LEN(@text) - @index))
END
ELSE
SET @text = RIGHT(@text, (LEN(@text) - @index))
END
RETURN
END
查询
select * from my_table inner join (select value from fn_split('ABC,MOP',','))
as split_table on my_table.column_name like '%'+split_table.value+'%';
对于Sql Server,您可以求助于动态Sql。
大多数情况下,在这种情况下,你有基于数据库中的一些数据的in子句参数。
下面的示例有点“勉强”,但这可以匹配遗留数据库中发现的各种真实情况。
假设您有一个Persons表,其中人名存储在一个字段PersonName中,即FirstName + ' ' + LastName。
您需要从名字列表中选择所有人,这些名字存储在表NamesToSelect中的NameToSelect字段中,再加上一些附加的条件(如按性别、出生日期等过滤)
你可以这样做
-- @gender is nchar(1), @birthDate is date
declare
@sql nvarchar(MAX),
@subWhere nvarchar(MAX)
@params nvarchar(MAX)
-- prepare the where sub-clause to cover LIKE IN (...)
-- it will actually generate where clause PersonName Like 'param1%' or PersonName Like 'param2%' or ...
set @subWhere = STUFF(
(
SELECT ' OR PersonName like ''' + [NameToSelect] + '%'''
FROM [NamesToSelect] t FOR XML PATH('')
), 1, 4, '')
-- create the dynamic SQL
set @sql ='select
PersonName
,Gender
,BirstDate -- and other field here
from [Persons]
where
Gender = @gender
AND BirthDate = @birthDate
AND (' + @subWhere + ')'
set @params = ' @gender nchar(1),
@birthDate Date'
EXECUTE sp_executesql @sql, @params,
@gender,
@birthDate