SQL Server:分割操作

如何在SQL Server中拆分string

例:

inputstring: stack over flow

结果:

 stack over flow 

如果您不能使用表值参数,请参阅Erland Sommarskog的“使用表值参数的SQL Server 2008中的数组和列表” ,然后在SQL Server中拆分string的方法很多。 本文涵盖了几乎所有方法的PRO和CON:

“SQL Server 2005及更高版本中的数组和列表,当表值参数不能削减”Erland Sommarskog

你需要创build一个拆分function。 这是如何使用拆分function:

 SELECT * FROM YourTable y INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value 

我更喜欢使用数字表格的方法来在TSQL中分割一个string,但是在SQL Server中有很多方法来拆分string,参见前面的链接,它解释了每个链接的PRO和CON。

要使数字表格方法起作用,您需要执行一次性表格设置,这将创build一个包含1到10,000行的表格的Numbers

 SELECT TOP 10000 IDENTITY(int,1,1) AS Number INTO Numbers FROM sys.objects s1 CROSS JOIN sys.objects s2 ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number) 

Numbers表设置好后,创build这个分割函数:

 CREATE FUNCTION [dbo].[FN_ListToTable] ( @SplitOn char(1) --REQUIRED, the character to split the @List string on ,@List varchar(8000)--REQUIRED, the list to split apart ) RETURNS TABLE AS RETURN ( ---------------- --SINGLE QUERY-- --this will not return empty rows ---------------- SELECT ListValue FROM (SELECT LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue FROM ( SELECT @SplitOn + @List + @SplitOn AS List2 ) AS dt INNER JOIN Numbers n ON n.Number < LEN(dt.List2) WHERE SUBSTRING(List2, number, 1) = @SplitOn ) dt2 WHERE ListValue IS NOT NULL AND ListValue!='' ); GO 

您现在可以轻松地将一个CSVstring拆分成一个表格并join:

 select * from dbo.FN_ListToTable(' ','stack over flow') 

OUTPUT:

 ListValue ------------------- stack over flow (3 row(s) affected) 

这种问题常见的基于集合的解决scheme是使用数字表。

以下解决scheme使用简单的recursionCTE来即时生成数字表 – 如果需要使用更长的string,则应该用静态数字表replace。

 DECLARE @vch_string varchar(max) DECLARE @chr_delim char(1) SET @chr_delim = ' ' SET @vch_string = 'stack over flow' ;WITH nums_cte AS ( SELECT 1 AS n UNION ALL SELECT n+1 FROM nums_cte WHERE n < len(@vch_string) ) SELECT n - LEN(REPLACE(LEFT(s,n),@chr_delim,'')) + 1 AS pos ,SUBSTRING(s,n,CHARINDEX(@chr_delim, s + @chr_delim,n) -n) as ELEMENT FROM (SELECT @vch_string as s) AS D JOIN nums_cte ON n <= LEN(s) AND SUBSTRING(@chr_delim + s,n,1) = @chr_delim OPTION (MAXRECURSION 0); 
 CREATE FUNCTION [dbo].[Split] ( @List varchar(max), @SplitOn nvarchar(5) ) RETURNS @RtnValue table ( Id int identity(1,1), Value nvarchar(max) ) AS BEGIN While (Charindex(@SplitOn,@List)>0) Begin Insert Into @RtnValue (value) Select Value = ltrim(rtrim(Substring(@List,1,Charindex(@SplitOn,@List)-1))) Set @List = Substring(@List,Charindex(@SplitOn,@List)+len(@SplitOn),len(@List)) End Insert Into @RtnValue (Value) Select Value = ltrim(rtrim(@List)) Return END 

创build以上function并执行下面的查询以获得您的结果。

 Select * From Dbo.Split('Stack Over Flow',' ') 

build议:使用分隔符来获取拆分值。 好多了。 (例如“堆叠,结束,stream动”)

我知道这个问题是为SQL Server 2008,但事情发展,所以从SQL Server 2016开始,你可以做到这一点

 DECLARE @string varchar(100) = 'Richard, Mike, Mark' SELECT value FROM string_split(@string, ',') 

硬。 真的很难 – Strin操纵和SQL … BAD组合。 一个存储过程的C#/ .NET是一种方式,可以返回一个表定义types(表)每行一个项目。