Lee*_*don 121 sql t-sql sql-server split sql-server-2008
我有一个SQL Server 2008 R2列包含一个字符串,我需要用逗号分隔.我在StackOverflow上看到了很多答案,但它们都不适用于R2.我确保我对任何拆分函数示例都有选择权限.任何帮助非常感谢.
And*_*son 203
我之前使用过这个SQL可能对你有用: -
CREATE FUNCTION dbo.splitstring ( @stringToSplit VARCHAR(MAX) )
RETURNS
@returnList TABLE ([Name] [nvarchar] (500))
AS
BEGIN
DECLARE @name NVARCHAR(255)
DECLARE @pos INT
WHILE CHARINDEX(',', @stringToSplit) > 0
BEGIN
SELECT @pos = CHARINDEX(',', @stringToSplit)
SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)
INSERT INTO @returnList
SELECT @name
SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
END
INSERT INTO @returnList
SELECT @stringToSplit
RETURN
END
Run Code Online (Sandbox Code Playgroud)
并使用它: -
SELECT * FROM dbo.splitstring('91,12,65,78,56,789')
Run Code Online (Sandbox Code Playgroud)
Aar*_*and 57
而不是递归CTE和while循环,有没有人考虑过更基于集合的方法?
CREATE FUNCTION dbo.SplitString
(
@List nvarchar(max),
@Delim nvarchar(255)
)
RETURNS TABLE
AS
RETURN ( SELECT [Value] FROM
(
SELECT [Value] = LTRIM(RTRIM(SUBSTRING(@List, [Number],
CHARINDEX(@Delim, @List + @Delim, [Number]) - [Number])))
FROM (SELECT Number = ROW_NUMBER() OVER (ORDER BY name)
FROM sys.all_columns) AS x WHERE Number <= LEN(@List)
AND SUBSTRING(@Delim + @List, [Number], DATALENGTH(@Delim)/2) = @Delim
) AS y
);
GO
Run Code Online (Sandbox Code Playgroud)
有关分割函数的更多信息,为什么(并证明)while循环和递归CTE不能缩放,以及更好的替代方法,如果分割来自应用程序层的字符串:
http://www.sqlperformance.com/2012/07/t-sql-queries/split-strings
http://www.sqlperformance.com/2012/08/t-sql-queries/splitting-strings-now-with-less-t-sql
https://sqlblog.org/2010/07/07/splitting-a-list-of-integers-another-roundup
Pரத*_*ீப் 46
最后等待在SQL Server 2016中结束了他们引入了Split字符串函数:STRING_SPLIT
select * From STRING_SPLIT ('a,b', ',') cs
Run Code Online (Sandbox Code Playgroud)
所有其他分割字符串的方法,如XML,Tally表,while循环等等,都被这个STRING_SPLIT函数所震撼.
以下是性能比较的优秀文章:性能惊喜和假设:STRING_SPLIT
Sar*_*avu 23
最简单的方法是使用XML格式.
1.将字符串转换为不带表的行
QUERY
DECLARE @String varchar(100) = 'String1,String2,String3'
-- To change ',' to any other delimeter, just change ',' to your desired one
DECLARE @Delimiter CHAR = ','
SELECT LTRIM(RTRIM(Split.a.value('.', 'VARCHAR(100)'))) 'Value'
FROM
(
SELECT CAST ('<M>' + REPLACE(@String, @Delimiter, '</M><M>') + '</M>' AS XML) AS Data
) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)
Run Code Online (Sandbox Code Playgroud)
结果
x---------x
| Value |
x---------x
| String1 |
| String2 |
| String3 |
x---------x
Run Code Online (Sandbox Code Playgroud)
2.从表中转换为具有每个CSV行的ID的行
消息表
x-----x--------------------------x
| Id | Value |
x-----x--------------------------x
| 1 | String1,String2,String3 |
| 2 | String4,String5,String6 |
x-----x--------------------------x
Run Code Online (Sandbox Code Playgroud)
QUERY
-- To change ',' to any other delimeter, just change ',' before '</M><M>' to your desired one
DECLARE @Delimiter CHAR = ','
SELECT ID,LTRIM(RTRIM(Split.a.value('.', 'VARCHAR(100)'))) 'Value'
FROM
(
SELECT ID,CAST ('<M>' + REPLACE(VALUE, @Delimiter, '</M><M>') + '</M>' AS XML) AS Data
FROM TABLENAME
) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)
Run Code Online (Sandbox Code Playgroud)
结果
x-----x----------x
| Id | Value |
x-----x----------x
| 1 | String1 |
| 1 | String2 |
| 1 | String3 |
| 2 | String4 |
| 2 | String5 |
| 2 | String6 |
x-----x----------x
Run Code Online (Sandbox Code Playgroud)
小智 9
我需要一个快速的方法来摆脱+4从一个邮政编码.
UPDATE #Emails
SET ZIPCode = SUBSTRING(ZIPCode, 1, (CHARINDEX('-', ZIPCODE)-1))
WHERE ZIPCode LIKE '%-%'
Run Code Online (Sandbox Code Playgroud)
没有proc ...没有UDF ...只是一个紧凑的小内联命令,它做了它必须做的事情.不花哨,不优雅.
根据需要更改分隔符等,它将适用于任何事情.
如果你更换
WHILE CHARINDEX(',', @stringToSplit) > 0
Run Code Online (Sandbox Code Playgroud)
同
WHILE LEN(@stringToSplit) > 0
Run Code Online (Sandbox Code Playgroud)
你可以在while循环之后消除最后一个插入!
CREATE FUNCTION dbo.splitstring ( @stringToSplit VARCHAR(MAX) )
RETURNS
@returnList TABLE ([Name] [nvarchar] (500))
AS
BEGIN
DECLARE @name NVARCHAR(255)
DECLARE @pos INT
WHILE LEN(@stringToSplit) > 0
BEGIN
SELECT @pos = CHARINDEX(',', @stringToSplit)
if @pos = 0
SELECT @pos = LEN(@stringToSplit)
SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)
INSERT INTO @returnList
SELECT @name
SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
END
RETURN
END
Run Code Online (Sandbox Code Playgroud)
小智 5
所有使用某种循环(迭代)的字符串分割函数的性能都很差。它们应该被基于集合的解决方案取代。
这段代码执行得非常好。
CREATE FUNCTION dbo.SplitStrings
(
@List NVARCHAR(MAX),
@Delimiter NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
(
SELECT Item = y.i.value('(./text())[1]', 'nvarchar(4000)')
FROM
(
SELECT x = CONVERT(XML, '<i>'
+ REPLACE(@List, @Delimiter, '</i><i>')
+ '</i>').query('.')
) AS a CROSS APPLY x.nodes('i') AS y(i)
);
GO
Run Code Online (Sandbox Code Playgroud)
XML 元素的常用方法在出现禁止字符的情况下会中断。这是一种将此方法用于任何类型的字符的方法,即使使用分号作为分隔符也是如此。
诀窍是,首先使用SELECT SomeString AS [*] FOR XML PATH('')来正确转义所有禁止的字符。这就是为什么我将分隔符替换为魔术值以避免使用;as 分隔符的麻烦的原因。
DECLARE @Dummy TABLE (ID INT, SomeTextToSplit NVARCHAR(MAX))
INSERT INTO @Dummy VALUES
(1,N'A&B;C;D;E, F')
,(2,N'"C" & ''D'';<C>;D;E, F');
DECLARE @Delimiter NVARCHAR(10)=';'; --special effort needed (due to entities coding with "&code;")!
WITH Casted AS
(
SELECT *
,CAST(N'<x>' + REPLACE((SELECT REPLACE(SomeTextToSplit,@Delimiter,N'§§Split$me$here§§') AS [*] FOR XML PATH('')),N'§§Split$me$here§§',N'</x><x>') + N'</x>' AS XML) AS SplitMe
FROM @Dummy
)
SELECT Casted.ID
,x.value(N'.',N'nvarchar(max)') AS Part
FROM Casted
CROSS APPLY SplitMe.nodes(N'/x') AS A(x)
Run Code Online (Sandbox Code Playgroud)
结果
ID Part
1 A&B
1 C
1 D
1 E, F
2 "C" & 'D'
2 <C>
2 D
2 E, F
Run Code Online (Sandbox Code Playgroud)