使用逗号分隔的字符串参数选择行

时间:2014-12-12 21:05:23

标签: sql sql-server tsql

我正在将存储过程从MySql转换为SQL Server。该过程有一个输入参数nvarchar / varchar,这是一个以逗号分隔的字符串,例如

'1,2,5,456,454,343,3464'

我需要编写一个将检索相关行的查询,在我正在使用FIND_IN_SET的MySql中,我想知道SQL Server中的等价物是什么。

我还需要在字符串中订购ID。

原始查询是:

 SELECT * 
 FROM table_name t
 WHERE FIND_IN_SET(id,p_ids)
 ORDER BY FIND_IN_SET(id,p_ids);

3 个答案:

答案 0 :(得分:2)

like的等效值为wherecharindex()的等效值为order by

select *
from table_name t
where ','+p_ids+',' like '%,'+cast(id as varchar(255))+',%'
order by charindex(',' + cast(id as varchar(255)) + ',', ',' + p_ids + ',');

嗯,你可以使用charindex(),但like可以在大多数数据库中使用。

请注意,我已在字符串的开头和结尾添加了分隔符,因此464不会意外地匹配3464。

答案 1 :(得分:1)

您需要编写FIND_IN_SET函数,因为它不存在。我能想到的将分隔字符串转换为可连接对象的closet机制是创建table-valued function并在标准语句中使用结果。它需要类似于:

DECLARE @MyParam NVARCHAR(3000)

SET @MyParam='1,2,5,456,454,343,3464'

SELECT 
    * 
FROM 
    MyTable 
WHERE 
    MyTableID IN (SELECT ID FROM dbo.MySplitDelimitedString(@MyParam,','))

您需要创建一个MySplitDelimitedString类型table-valued function来分割字符串并返回TABLE (ID INT)个对象。

答案 2 :(得分:0)

基于集合的解决方案,它将id分成int并与基表连接,后者将利用基表id上的索引。我假设id是一个int,否则只需删除强制转换。

declare @ids nvarchar(100) = N'1,2,5,456,454,343,3464';

with nums as ( -- Generate numbers
    select top (len(@ids)) row_number() over (order by (select 0)) n
    from sys.messages
)
, pos1 as ( -- Get comma positions
    select c.ci
    from nums n
        cross apply (select charindex(',', @ids, n.n) as ci) c
    group by c.ci
)
, pos2 as ( -- Distinct posistions plus start and end
    select ci
    from pos1
    union select 0
    union select len(@ids) + 1
)
, pos3 as ( -- add row number for join
    select ci, row_number() over (order by ci) as r
    from pos2
)
, ids as ( -- id's and row id for ordering
    select cast(substring(@ids, p1.ci + 1, p2.ci - p1.ci - 1) as int) id, row_number() over (order by p1.ci) r
    from pos3 p1
        inner join pos3 p2 on p2.r = p1.r + 1
)
select *
from ids i
    inner join table_name t on t.id = i.id
order by i.r;