请帮助如何用逗号分隔字符串中的单词
例如:'abcdef'
输出:'a,b,c,d,e,f'
答案 0 :(得分:5)
如果你想操作tsql变量:
DECLARE @str VARCHAR(40) = 'abcdef'
您可以使用以下代码使用spt_values
创建一个标记,并在字符串中STUFF注入,
字符:
SELECT @str = STUFF(@str, Number * 2, 0, ',')
FROM [master].[dbo].[spt_values]
WHERE Type = 'P' AND
Number BETWEEN 1 AND LEN(@str) - 1
执行上述操作后,@str
为a,b,c,d,e,f
。
答案 1 :(得分:3)
这在纯SQL中并不是最好的处理,并且更适合应用程序层或CLR,但一种解决方案是将字符串拆分为单独的组件,然后使用逗号分隔符重建它。要首先执行此操作,您需要一个数字表,以下系列深入探讨了执行此操作的最佳方法:
为了答案,我假设您没有数字表,需要动态创建一个,最有效的方法是使用堆叠CTE。以下将返回从1到10000的列表:
WITH N1 AS (SELECT N FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (N)),
N2 (N) AS (SELECT 1 FROM N1 AS N1 CROSS JOIN N1 AS N2),
N3 (N) AS (SELECT 1 FROM N2 AS N1 CROSS JOIN N2 AS N2),
Numbers (Number) AS (SELECT ROW_NUMBER() OVER(ORDER BY N) FROM N3)
SELECT *
FROM Numbers;
然后您可以使用这些数字来分割字符串:
DECLARE @T TABLE (Col VARCHAR(10));
INSERT @T VALUES ('abcdef');
WITH N1 AS (SELECT N FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (N)),
N2 (N) AS (SELECT 1 FROM N1 AS N1 CROSS JOIN N1 AS N2),
N3 (N) AS (SELECT 1 FROM N2 AS N1 CROSS JOIN N2 AS N2),
Numbers (Number) AS (SELECT ROW_NUMBER() OVER(ORDER BY N) FROM N3)
SELECT *,
Letter = SUBSTRING(t.Col, n.Number, 1)
FROM @T AS t
INNER JOIN Numbers n
ON n.Number <= LEN(t.Col);
这会给你:
Col Number Letter
------------------------
abcdef 1 a
abcdef 2 b
abcdef 3 c
abcdef 4 d
abcdef 5 e
abcdef 6 f
然后,您可以使用SQL Servers XML extensions重建字符串:
DECLARE @T TABLE (Col VARCHAR(10));
INSERT @T VALUES ('abcdef'), ('test');
WITH N1 AS (SELECT N FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (N)),
N2 (N) AS (SELECT 1 FROM N1 AS N1 CROSS JOIN N1 AS N2),
N3 (N) AS (SELECT 1 FROM N2 AS N1 CROSS JOIN N2 AS N2),
Numbers (Number) AS (SELECT ROW_NUMBER() OVER(ORDER BY N) FROM N3)
SELECT t.Col,
Split = ( SELECT CASE WHEN n.Number = 1 THEN '' ELSE ',' END + SUBSTRING(t2.Col, n.Number, 1)
FROM @T AS t2
INNER JOIN Numbers n
ON n.Number <= LEN(t2.Col)
WHERE t2.Col = t.Col
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
FROM @T AS t;
此方法的好处是您可以将其用作内联表值函数:
CREATE FUNCTION dbo.InjectDelimiter (@String VARCHAR(1000), @Delimiter CHAR(1))
RETURNS TABLE
AS
RETURN
( WITH N1 AS (SELECT N FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (N)),
N2 (N) AS (SELECT 1 FROM N1 AS N1 CROSS JOIN N1 AS N2),
N3 (N) AS (SELECT 1 FROM N2 AS N1 CROSS JOIN N2 AS N2),
Numbers (Number) AS (SELECT ROW_NUMBER() OVER(ORDER BY N) FROM N3)
SELECT Split = ( SELECT CASE WHEN n.Number = 1 THEN '' ELSE @Delimiter END + SUBSTRING(@String, n.Number, 1)
FROM Numbers n
WHERE n.Number <= LEN(@String)
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
);
然后你可以把它称为:
SELECT t.Name, i.Split
FROM sys.tables AS t
CROSS APPLY dbo.InjectDelimiter(t.name, ',') AS i;
如果你需要在多行上调用它,那么它的性能会比标量函数好得多。
答案 2 :(得分:1)
我会使用while循环:
DECLARE @str VARCHAR(max) = 'abcdef'
DECLARE @loop INT = LEN(@str)
WHILE @loop > 1
SELECT @str = STUFF(@str, @loop, 0, ','), @loop -= 1
SELECT @str
答案 3 :(得分:0)
您可以为此
创建以下功能CREATE FUNCTION PutCommasBetweenChars
(@String VARCHAR(100))
RETURNS VARCHAR(100)
AS
BEGIN
DECLARE @pos INT, @result VARCHAR(100);
SET @result = @String;
SET @pos = 2 -- location where we want first space
WHILE @pos < LEN(@result)+1
BEGIN
SET @result = STUFF(@result, @pos, 0, ',');
SET @pos = @pos+2;
END
RETURN @result;
END
GO
按以下步骤执行
print dbo.PutCommasBetweenChars('abcdef')
答案 4 :(得分:0)
前一段时间我想出了这个解决方案:
Declare @separator as nvarchar(1)= ','
Declare @filterlist as nvarchar(MAX) = '1,2,3,4,5'
IF OBJECT_ID('tempdb..#filterList') IS NOT NULL
DROP TABLE #filterlist
--Create temporary filter list table
create table #FilterList (
filter varchar(100) Not NULL
)
--Add 1 comma to the filter list, used for processing the list
set @filterlist = @filterList + @separator
--Declare and set default variable values for processing Filter list
DECLARE @pos INT
DECLARE @len INT
DECLARE @value varchar(100)
set @pos = 0
set @len = 0
--Loop thru the string of filter list, separate the , values and insert into the #Filterlist
WHILE CHARINDEX(@separator , @filterList, @pos+1)>0
BEGIN
set @len = CHARINDEX(@separator , @filterList, @pos+1) - @pos
set @value = SUBSTRING(@filterList, @pos, @len)
insert Into #FilterList (filter) Values(@value)
set @pos = CHARINDEX(@separator , @filterList, @pos+@len) + 1
END
select * from #FilterList
答案 5 :(得分:0)
花了一些时间后我找到了你的解决方案
DECLARE @Chars VARCHAR(8000)
SELECT @Chars = COALESCE(@Names + ', ', '') + Main.SplitChar
FROM
(
select (substring(a.b, v.number+1, 1)) AS SplitChar
from (select 'QWERTY' b) a
join master..spt_values v on v.number < len(a.b)
where v.type = 'P'
) AS MaIn
SELECT @Chars
请告诉我,是否有效。 :)
答案 6 :(得分:0)
Thank you all ! I tried below code, but I got better answers from you all guys
CREATE TABLE #TEMP (ID INT IDENTITY, CHARR VARCHAR(MAX))
DECLARE @DATA NVARCHAR(MAX)='ABCDEFG'
DECLARE @LEN INT = LEN(@DATA)
DECLARE @INT INT = 1
WHILE @INT<=@LEN
BEGIN
INSERT INTO #TEMP VALUES (SUBSTRING(@DATA,@INT,1))
SET @INT=@INT+1
end
SELECT STUFF(
(SELECT ',' + S.CHARR
FROM #TEMP s
ORDER BY s.ID
FOR XML PATH('')),1,1,'') AS CSV