我有以下Split
功能,
ALTER FUNCTION [dbo].[Split](@String varchar(8000), @Delimiter char(1))
returns @temptable TABLE (items varchar(8000))
as
begin
set @String = RTRIM(LTRIM(@String))
declare @idx int
declare @slice varchar(8000)
select @idx = 1
if len(@String)<1 or @String is null return
while @idx!= 0
begin
set @idx = charindex(@Delimiter,@String)
if @idx!=0
set @slice = left(@String,@idx - 1)
else
set @slice = @String
if(len(@slice)>0)
insert into @temptable(Items) values(@slice)
set @String = right(@String,len(@String) - @idx)
if len(@String) = 0 break
end
return
end
当我写作时,
SELECT Items
FROM Split('around the home,clean and protect,soaps and air fresheners,air fresheners',',')
这会给我,
air fresheners
around the home
clean and protect
soaps and air fresheners
我需要维持秩序。
答案 0 :(得分:4)
一个更简单的功能:
CREATE FUNCTION dbo.SplitStrings_Ordered
(
@List nvarchar(MAX),
@Delimiter nvarchar(255)
)
RETURNS TABLE
AS
RETURN
(
SELECT [Index] = CHARINDEX(@Delimiter, @List + @Delimiter, Number),
Item = SUBSTRING(@List, Number, CHARINDEX(@Delimiter,
@List + @Delimiter, Number) - Number)
FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY [object_id]) FROM sys.all_objects
) AS n(Number)
WHERE Number <= CONVERT(INT, LEN(@List))
AND SUBSTRING(@Delimiter + @List, Number, LEN(@Delimiter)) = @Delimiter
);
GO
样本用法:
DECLARE @s nvarchar(MAX) = N',around the home,clean and protect,soaps and air'
+ ' fresheners,air fresheners';
SELECT Item FROM dbo.SplitStrings_Ordered(@s, N',') ORDER BY [Index];
或者从输入订购的表中返回订单:
SELECT o.OrderID
FROM dbo.Orders AS o
INNER JOIN dbo.SplitStrings_Ordered('123,789,456') AS f
ON o.OrderID = CONVERT(int, f.Item)
ORDER BY f.[Index];
答案 1 :(得分:1)
您的函数需要设置一个订单列(此示例中为seq):
ALTER FUNCTION [dbo].[Split](@String varchar(8000), @Delimiter char(1))
returns @temptable TABLE (seq int, items varchar(8000))
as
begin
set @String = RTRIM(LTRIM(@String))
declare @idx int
declare @seq int
declare @slice varchar(8000)
set @seq=1
select @idx = 1
if len(@String)<1 or @String is null return
while @idx!= 0
begin
set @idx = charindex(@Delimiter,@String)
if @idx!=0
set @slice = left(@String,@idx - 1)
else
set @slice = @String
if(len(@slice)>0)
begin
set @seq = @seq + 1
insert into @temptable(seq, Items) values(@seq,@slice)
end
set @String = right(@String,len(@String) - @idx)
if len(@String) = 0 break
end
return
end
GO
SELECT * FROM Split('around the home,clean and protect,soaps and air fresheners,air fresheners',',') order by seq
答案 2 :(得分:1)
declare @Version nvarchar(3000)
declare @Delimiter char(1) = ','
declare @result nvarchar(3000)
set @Version = 'Terça-feira, Quarta-feira, Sexta-feira, Segunda-feira';
with V as (select value v, Row_Number() over (order by (select 0)) n
from String_Split(@Version, @Delimiter)
)
SELECT @result = STUFF((SELECT ', ' + RTRIM(LTRIM(v))
FROM V
ORDER BY CASE RTRIM(LTRIM(v))
WHEN 'Segunda-feira' then 1
WHEN 'Terça-feira' then 2
WHEN 'Quarta-feira' then 3
WHEN 'Quinta-feira' then 4
WHEN 'Sexta-feira' then 5
END FOR XML PATH('')), 1, LEN(@Delimiter), '')
PRINT @result
答案 3 :(得分:0)
如果您可以遵守SQL Server的兼容级别130,则可以使用String_Split()
函数。
使用此函数和Row_Number()函数,您可以返回包含原始序列的表。例如:
declare @Version nvarchar(128)
set @Version = '1.2.3';
with V as (select value v, Row_Number() over (order by (select 0)) n
from String_Split(@Version, '.')
)
select
(select v from V where n = 1) Major,
(select v from V where n = 2) Minor,
(select v from V where n = 3) Revision
请注意,Row_Number需要排序,但是如果您传递文字值,则结果将位于解析的序列中。不能保证将来的SQL Server版本会发生这种情况,因为根据String_Split文档,没有正式订购。我怀疑微软是否会破坏这一点,至少在引入该功能的版本之前应按顺序返回该命令,但是与此同时,在编写决定是否发射导弹的代码时,最好不要依赖此命令。 / p>
返回:
Major Minor Revision
----- ----- --------
1 2 3
答案 4 :(得分:0)
当您的字符串具有1000个或更多的值要拆分时,这将是一个更快的解决方案。对于表值函数,要进行任何排序,必须在使用位置应用“ ORDER BY”。这是因为按照惯例,没有“ ORDER BY”的表中的“ SELECT”没有任何排序。
CREATE FUNCTION [dbo].[Split]
(
@String VARCHAR(max),
@Delimiter VARCHAR(max)
)
RETURNS @Data TABLE
(
[Order] INT IDENTITY(1,1),
[Value] VARCHAR(max)
)
AS
BEGIN
DECLARE @x XML = cast('<i>' + replace(@String, @Delimiter, '</i><i>') + '</i>' AS XML)
INSERT INTO @Data
SELECT v.value('.', 'varchar(max)') FROM @x.nodes('i') AS x(v)
RETURN
END
GO