热将值为 '1,2,3' 的变量转换为 table(每个数字作为记录)
Hot to convert a variable with value '1,2,3' to a table (every number as a record)
致力于 SQL(2005 年和 2008 年)
值为“1,2,3”的变量将调用@cedis,例如这可能有 N 个数字
set @cedis='1' or set @cedis='1,2,3,4,5,6,7' or set @cedis='125,98,91'
这么重要,这个必须是select而已,不能用循环,只有select!
这必须 return a(结果为)table,例如
set @cedis='1,2,3,4' this must to return a result
number 1 2 3 4
declare @cedis varchar(max)
set @cedis='1,58,123,8'
;with datos as
(
my select with is going to return me the table
)
select * from datos
结果集是
number
1
58
123
8
如果我没记错,这就是你需要的
DECLARE @cedis VARCHAR(500)='1,2,3,4'
SELECT Split.a.value('.', 'VARCHAR(100)') Numbers
FROM (SELECT Cast ('<M>' + Replace(@cedis, ',', '</M><M>') + '</M>' AS XML) AS Numbers) AS A
CROSS APPLY Numbers.nodes ('/M') AS Split(a)
结果:
Numbers
-------
1
2
3
4
一个table值函数就可以做到。
CREATE FUNCTION [dbo].[fn_Split](@text VARCHAR(MAX), @delimiter VARCHAR(5) = ',')
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))
END
SET @text = RIGHT(@text, (LEN(@text) - (@index+LEN(@delimiter)-1)))
END
RETURN
END
您可以这样调用:
SELECT *
FROM dbo.fn_Split(@cedis,',')
这是一个更通用的解决方案,它根据任何给定的分隔符将任何给定的字符串分解为 table:
http://rextester.com/VSRDLS48817
不是原创,但我发现它非常有用。
create function [dbo].[SplitString]
(
@str nvarchar(255),
@separator char(1)
)
returns table
AS
return (
with tokens(p, a, b) AS (
select
cast(1 as int),
cast(1 as int),
charindex(@separator, @str)
union all
select
p + 1,
b + 1,
charindex(@separator, @str, b + 1)
from tokens
where b > 0
)
select
p-1 ItemIndex,
substring(
@str,
a,
case when b > 0 then b-a ELSE LEN(@str) end)
AS Item
from tokens
);
这是获得所需输出结果的另一种方法
DECLARE @cedis VARCHAR(MAX) ,
@delimeter VARCHAR(10)
SET @cedis = '1,58,123,8,14144,15,155231,15,3647,2347,45,76,68,2354,577,5'
SET @delimeter = ','
SET @cedis = @cedis + @delimeter;
WITH datos
AS ( SELECT n = 1
UNION ALL
SELECT n + 1
FROM datos
WHERE n <= LEN(@cedis)
),
cte
AS ( SELECT T.N ,
ROW_NUMBER() OVER ( ORDER BY T.N ) AS RN
FROM datos AS T
WHERE SUBSTRING(@cedis, T.N, LEN(@delimeter)) = @delimeter
AND LEN(@cedis) >= T.N
)
SELECT SUBSTRING(@cedis, COALESCE(R.N + LEN(@delimeter), 1),
L.N - COALESCE(R.N + LEN(@delimeter), 1)) AS part ,
L.RN AS ID
FROM cte AS L
LEFT JOIN cte AS R ON L.RN = R.RN + 1
OPTION ( MAXRECURSION 1000 )
致力于 SQL(2005 年和 2008 年)
值为“1,2,3”的变量将调用@cedis,例如这可能有 N 个数字
set @cedis='1' or set @cedis='1,2,3,4,5,6,7' or set @cedis='125,98,91'
这么重要,这个必须是select而已,不能用循环,只有select!
这必须 return a(结果为)table,例如
set @cedis='1,2,3,4' this must to return a result number 1 2 3 4 declare @cedis varchar(max) set @cedis='1,58,123,8' ;with datos as ( my select with is going to return me the table ) select * from datos
结果集是
number
1
58
123
8
如果我没记错,这就是你需要的
DECLARE @cedis VARCHAR(500)='1,2,3,4'
SELECT Split.a.value('.', 'VARCHAR(100)') Numbers
FROM (SELECT Cast ('<M>' + Replace(@cedis, ',', '</M><M>') + '</M>' AS XML) AS Numbers) AS A
CROSS APPLY Numbers.nodes ('/M') AS Split(a)
结果:
Numbers
-------
1
2
3
4
一个table值函数就可以做到。
CREATE FUNCTION [dbo].[fn_Split](@text VARCHAR(MAX), @delimiter VARCHAR(5) = ',')
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))
END
SET @text = RIGHT(@text, (LEN(@text) - (@index+LEN(@delimiter)-1)))
END
RETURN
END
您可以这样调用:
SELECT *
FROM dbo.fn_Split(@cedis,',')
这是一个更通用的解决方案,它根据任何给定的分隔符将任何给定的字符串分解为 table:
http://rextester.com/VSRDLS48817
不是原创,但我发现它非常有用。
create function [dbo].[SplitString]
(
@str nvarchar(255),
@separator char(1)
)
returns table
AS
return (
with tokens(p, a, b) AS (
select
cast(1 as int),
cast(1 as int),
charindex(@separator, @str)
union all
select
p + 1,
b + 1,
charindex(@separator, @str, b + 1)
from tokens
where b > 0
)
select
p-1 ItemIndex,
substring(
@str,
a,
case when b > 0 then b-a ELSE LEN(@str) end)
AS Item
from tokens
);
这是获得所需输出结果的另一种方法
DECLARE @cedis VARCHAR(MAX) ,
@delimeter VARCHAR(10)
SET @cedis = '1,58,123,8,14144,15,155231,15,3647,2347,45,76,68,2354,577,5'
SET @delimeter = ','
SET @cedis = @cedis + @delimeter;
WITH datos
AS ( SELECT n = 1
UNION ALL
SELECT n + 1
FROM datos
WHERE n <= LEN(@cedis)
),
cte
AS ( SELECT T.N ,
ROW_NUMBER() OVER ( ORDER BY T.N ) AS RN
FROM datos AS T
WHERE SUBSTRING(@cedis, T.N, LEN(@delimeter)) = @delimeter
AND LEN(@cedis) >= T.N
)
SELECT SUBSTRING(@cedis, COALESCE(R.N + LEN(@delimeter), 1),
L.N - COALESCE(R.N + LEN(@delimeter), 1)) AS part ,
L.RN AS ID
FROM cte AS L
LEFT JOIN cte AS R ON L.RN = R.RN + 1
OPTION ( MAXRECURSION 1000 )