我将以下字符串分为两列:
给出:
DECLARE @String VARCHAR(MAX) = 'Mak^1,Jak^2,Smith^3,Lee^4,Joseph^5'
我想将其分为两列:
column1 column2
-----------------
Mak 1
Jak 2
Smith 3
Lee 4
Joseph 5
我的尝试:
表值函数:
CREATE FUNCTION [dbo].[udf_Split]
(
@InputString VARCHAR(8000),
@Delimiter VARCHAR(50)
)
RETURNS @Items TABLE (ID INTEGER IDENTITY(1,1), Item VARCHAR(8000))
AS
BEGIN
IF @Delimiter = ' '
BEGIN
SET @Delimiter = ','
SET @InputString = REPLACE(@InputString, ' ', @Delimiter)
END
IF (@Delimiter IS NULL OR @Delimiter = '')
SET @Delimiter = ','
DECLARE @Item VARCHAR(8000)
DECLARE @ItemList VARCHAR(8000)
DECLARE @DelimIndex INT
SET @ItemList = @InputString
SET @DelimIndex = CHARINDEX(@Delimiter, @ItemList, 0)
WHILE (@DelimIndex != 0)
BEGIN
SET @Item = SUBSTRING(@ItemList, 0, @DelimIndex)
INSERT INTO @Items VALUES (@Item)
SET @ItemList = SUBSTRING(@ItemList, @DelimIndex+1, LEN(@ItemList)-@DelimIndex)
SET @DelimIndex = CHARINDEX(@Delimiter, @ItemList, 0)
END -- End WHILE
IF @Item IS NOT NULL
BEGIN
SET @Item = @ItemList
INSERT INTO @Items VALUES (@Item)
END
ELSE INSERT INTO @Items VALUES (@InputString)
RETURN
END
函数调用:
SELECT Item FROM [dbo].[udf_Split](@String ,',');
输出:
Item
--------------
Mak^1
Jak^2
Smith^3
Lee^4
Joseph^5
答案 0 :(得分:4)
首先,请注意,SQL Server 2008 r2不在扩展支持范围内。现在是升级到较新版本的时候了。
对于单个字符串,我可能会使用一些动态SQL魔术:
DECLARE @String VARCHAR(MAX) = 'Mak^1,Jak^2,Smith^3,Lee^4,Joseph^5'
DECLARE @Sql VARCHAR(MAX) = 'SELECT Name,Id FROM (VALUES (''' + REPLACE(REPLACE(REPLACE(@String,'''',''''''), ',', '),('''), '^', ''',') + ')) V(Name, Id)';
-- @Sql now contains this:
-- SELECT Name,Id FROM (VALUES ('Mak',1),('Jak',2),('Smith',3),('Lee',4),('Joseph',5)) V(Name, Id)
EXEC(@Sql)
结果:
Name Id
Mak 1
Jak 2
Smith 3
Lee 4
Joseph 5
答案 1 :(得分:1)
在下面尝试此脚本
DECLARE @String VARCHAR(MAX) = 'Mak^1,Jak^2,Smith^3,Lee^4,Joseph^5';
DECLARE @TempTable AS TABLE(data VARCHAR(MAX))
INSERT INTO @TempTable
SELECT @String
;WITH CTE
AS
(
SELECT Split.A.value('.','nvarchar(1000)') AS data
FROM
(
SELECT CAST('<S>'+REPLACE(data,',','</S><S>')+'</S>' AS XML ) AS data
FROM @TempTable
)AS A
CROSS APPLY data.nodes('S') AS Split(A)
)
SELECT LTRIM(RTRIM(SUBSTRING(data,0,CHARINDEX('^',data)))) AS column1,
LTRIM(RTRIM(SUBSTRING(data,CHARINDEX('^',data)+1,LEN (data)))) AS column2
FROM CTE
结果
column1 column2
-------------------
Mak 1
Jak 2
Smith 3
Lee 4
Joseph 5
使用上述脚本创建表值参数函数
CREATE FUNCTION [dbo].[udf_SplitFun](@InputData VARCHAR(MAX))
RETURNS @Return TABLE ( column1 VARCHAR(200),column2 INT)
AS
BEGIN
DECLARE @TempTable AS TABLE
(
data VARCHAR(MAX)
)
INSERT INTO @TempTable
SELECT @InputData
;WITH CTE
AS
(
SELECT Split.A.value('.','nvarchar(1000)') AS data
FROM
(
SELECT CAST('<S>'+REPLACE(data,',','</S><S>')+'</S>' AS XML ) AS data
FROM @TempTable
)AS A
CROSS APPLY data.nodes('S') AS Split(A)
)
INSERT INTO @Return(column1,column2)
SELECT LTRIM(RTRIM(SUBSTRING(data,0,CHARINDEX('^',data)))) AS column1,
LTRIM(RTRIM(SUBSTRING(data,CHARINDEX('^',data)+1,LEN (data)))) AS column2
FROM CTE
RETURN;
END
执行如下所示的功能
DECLARE @InputData VARCHAR(MAX) = 'Mak^1,Jak^2,Smith^3,Lee^4,Joseph^5';
SELECT * FROM [dbo].[udf_SplitFun] (@InputData)
GO
答案 2 :(得分:1)
我觉得更好的方法是摆脱可怕的WHILE
并使用基于集合的方法;我们将在这里使用delimitedsplit8K
(如果您使用的是2012+,请使用delimitedsplit8k_lead
或使用2016+的用户,可以使用STRING_SPLIT
)。
考虑到这一点,以上内容变得很简单:
DECLARE @String varchar(MAX) = 'Mak^1,Jak^2,Smith^3,Lee^4,Joseph^5';
SELECT LEFT(DS.Item,CHARINDEX('^',DS.Item)-1) AS Col1,
STUFF(DS.Item,1, CHARINDEX('^',DS.Item),'') AS Col2
FROM dbo.DelimitedSplit8K(@String, ',') DS;
答案 3 :(得分:1)
在最新版本的SQL Server中,您可以使用string_split()
:
select left(s.value, charindex('^', value) - 1) as column1,
stuff(s.value, 1, charindex('^', value), '') as column2
from string_split(@string, ',') s ;
您可能会发现下载拆分函数来处理此问题最为方便。
否则,我认为递归CTE是一种简单的方法:
with cte as (
select convert(varchar(max), null) as row,
@string as str
union all
select convert(varchar(max), left(str, charindex(',', str + ',') - 1)),
convert(varchar(max), stuff(str, 1, charindex(',', str + ','), ''))
from cte
where str <> ''
)
select left(cte.row, charindex('^', cte.row) - 1) as column1,
stuff(cte.row, 1, charindex('^', cte.row), '')
from cte
where row is not null;
Here是db <>小提琴。
答案 4 :(得分:1)
您可以再次使用该拆分功能来按插入号拆分每行。喜欢:
SELECT SplitByCaret1.Item, SplitByCaret2.Item
FROM [dbo].[udf_Split](@String ,',') SplitByComma
CROSS APPLY (SELECT * FROM [dbo].[udf_Split](SplitByComma.Item ,'^') Splitted WHERE Splitted.ID=1) SplitByCaret1
CROSS APPLY (SELECT * FROM [dbo].[udf_Split](SplitByComma.Item ,'^') Splitted WHERE Splitted.ID=2) SplitByCaret2