TSQL 解析带 4 个分隔符的字符串
TSQL Parse String with 4 delimiters
我正在尝试解析这个字符串:
'200|50|jo.th@xxx.com|0916|07:00:00'
分为 5 列,我感到很沮丧。
分隔符是竖线 |
字段不固定,所以我需要使用 charindex 才能找到分隔符的位置?
请帮忙
谢谢
所以首先我会找到每个定界符的位置,然后用它来分割你的字符串。像这样;
DECLARE @TextString nvarchar(100); SET @TextString = '200|50|jo.th@xxx.com|0916|07:00:00'
DECLARE @FirstDelimiter int
DECLARE @SecondDelimiter int
DECLARE @ThirdDelimiter int
DECLARE @FourthDelimiter int
SET @FirstDelimiter = CHARINDEX('|',@TextString)
SET @SecondDelimiter = CHARINDEX('|',@TextString,@FirstDelimiter+1)
SET @ThirdDelimiter = CHARINDEX('|',@TextString,@SecondDelimiter+1)
SET @FourthDelimiter = CHARINDEX('|',@TextString,@ThirdDelimiter+1)
最终查询;
SELECT
@TextString Main_String
,SUBSTRING(@TextString,1,@FirstDelimiter-1) First_String
,SUBSTRING(@TextString,@FirstDelimiter+1,(@SecondDelimiter-@FirstDelimiter)-1) Second_String
,SUBSTRING(@TextString,@SecondDelimiter+1,(@ThirdDelimiter-@SecondDelimiter)-1) Third_String
,SUBSTRING(@TextString,@ThirdDelimiter+1,(@FourthDelimiter-@ThirdDelimiter)-1) Fourth_String
,SUBSTRING(@TextString,@FourthDelimiter+1,LEN(@TextString)-@FourthDelimiter) Fifth_String
结果集;
Main_String First_String Second_String Third_String Fourth_String Fifth_String
200|50|jo.th@xxx.com|0916|07:00:00 200 50 jo.th@xxx.com 0916 07:00:00
另一个选项如下。这可以烘焙到 TVF 甚至交叉应用
Declare @String varchar(max) = '200|50|jo.th@xxx.com|0916|07:00:00'
Select Pos1 = xDim.value('/x[1]','varchar(max)')
,Pos2 = xDim.value('/x[2]','varchar(max)')
,Pos3 = xDim.value('/x[3]','varchar(max)')
,Pos4 = xDim.value('/x[4]','varchar(max)')
,Pos5 = xDim.value('/x[5]','varchar(max)')
,Pos6 = xDim.value('/x[6]','varchar(max)')
,Pos7 = xDim.value('/x[7]','varchar(max)')
,Pos8 = xDim.value('/x[8]','varchar(max)')
,Pos9 = xDim.value('/x[9]','varchar(max)')
From (Select Cast('<x>' + Replace(@String,'|','</x><x>')+'</x>' as XML) as xDim) A
Returns
Edit - To Use in a Cross Apply - Easy to expand/contract
Declare @YourTable table (ID int,SomeString varchar(max))
Insert Into @YourTable values
(1,'200|50|jo.th@xxx.com|0916|07:00:00'),
(2,'400|99|james.th@xxx.com|1116|09:00:00')
Select A.ID
,B.*
From @YourTable A
Cross Apply (
Select Pos1 = xDim.value('/x[1]','varchar(max)')
,Pos2 = xDim.value('/x[2]','varchar(max)')
,Pos3 = xDim.value('/x[3]','varchar(max)')
,Pos4 = xDim.value('/x[4]','varchar(max)')
,Pos5 = xDim.value('/x[5]','varchar(max)')
,Pos6 = xDim.value('/x[6]','varchar(max)')
,Pos7 = xDim.value('/x[7]','varchar(max)')
,Pos8 = xDim.value('/x[8]','varchar(max)')
,Pos9 = xDim.value('/x[9]','varchar(max)')
From (Select Cast('<x>' + Replace(A.SomeString,'|','</x><x>')+'</x>' as XML) as xDim) A
) B
Returns
我使用以下方法将分隔值放入一组表行中(通常用于在存储过程参数中传递多个值,然后可以将其连接),旋转可以将其转换为列。
(与 SQL Server 2005 及更高版本兼容)
DECLARE @Input varchar(MAX)
DECLARE @Delim char(1)
SET @Input = '200|50|jo.th@xxx.com|0916|07:00:00'
SET @Delim = '|'
DECLARE @VALUES TABLE (ColNo INT, [Param] varchar(MAX))
DECLARE @ChrInd INT
DECLARE @Piece varchar(MAX)
DECLARE @ColNo INT
SET @ColNo = 1
SELECT @ChrInd = 1
WHILE @ChrInd > 0
BEGIN
SELECT @ChrInd = CHARINDEX(@Delim,@Input)
IF @ChrInd > 0
SELECT @Piece = LEFT(@Input,@ChrInd - 1)
ELSE
SELECT @Piece = @Input
INSERT INTO @VALUES(ColNo, [Param]) VALUES(@ColNo, @Piece)
SELECT @Input = RIGHT(@Input,LEN(@Input) - @ChrInd)
IF LEN(@Input) = 0 BREAK
SET @ColNo = @ColNo + 1
END
--SELECT AS ROWS
SELECT * FROM @VALUES
--SELECT AS COLUMNS
SELECT * FROM
(
SELECT ColNo, [Param] FROM @VALUES
) src
PIVOT(
MAX([Param])
FOR ColNo IN ([1],[2],[3],[4],[5])
) AS pvt
结果
ColNo Param
--------------------------------------------------------------------------
1 200
2 50
3 jo.th@xxx.com
4 0916
5 07:00:00
1 2 3 4 5
--------- --------- --------------- ----------- ----------
200 50 jo.th@xxx.com 0916 07:00:00
我正在尝试解析这个字符串:
'200|50|jo.th@xxx.com|0916|07:00:00'
分为 5 列,我感到很沮丧。
分隔符是竖线 |
字段不固定,所以我需要使用 charindex 才能找到分隔符的位置?
请帮忙 谢谢
所以首先我会找到每个定界符的位置,然后用它来分割你的字符串。像这样;
DECLARE @TextString nvarchar(100); SET @TextString = '200|50|jo.th@xxx.com|0916|07:00:00'
DECLARE @FirstDelimiter int
DECLARE @SecondDelimiter int
DECLARE @ThirdDelimiter int
DECLARE @FourthDelimiter int
SET @FirstDelimiter = CHARINDEX('|',@TextString)
SET @SecondDelimiter = CHARINDEX('|',@TextString,@FirstDelimiter+1)
SET @ThirdDelimiter = CHARINDEX('|',@TextString,@SecondDelimiter+1)
SET @FourthDelimiter = CHARINDEX('|',@TextString,@ThirdDelimiter+1)
最终查询;
SELECT
@TextString Main_String
,SUBSTRING(@TextString,1,@FirstDelimiter-1) First_String
,SUBSTRING(@TextString,@FirstDelimiter+1,(@SecondDelimiter-@FirstDelimiter)-1) Second_String
,SUBSTRING(@TextString,@SecondDelimiter+1,(@ThirdDelimiter-@SecondDelimiter)-1) Third_String
,SUBSTRING(@TextString,@ThirdDelimiter+1,(@FourthDelimiter-@ThirdDelimiter)-1) Fourth_String
,SUBSTRING(@TextString,@FourthDelimiter+1,LEN(@TextString)-@FourthDelimiter) Fifth_String
结果集;
Main_String First_String Second_String Third_String Fourth_String Fifth_String
200|50|jo.th@xxx.com|0916|07:00:00 200 50 jo.th@xxx.com 0916 07:00:00
另一个选项如下。这可以烘焙到 TVF 甚至交叉应用
Declare @String varchar(max) = '200|50|jo.th@xxx.com|0916|07:00:00'
Select Pos1 = xDim.value('/x[1]','varchar(max)')
,Pos2 = xDim.value('/x[2]','varchar(max)')
,Pos3 = xDim.value('/x[3]','varchar(max)')
,Pos4 = xDim.value('/x[4]','varchar(max)')
,Pos5 = xDim.value('/x[5]','varchar(max)')
,Pos6 = xDim.value('/x[6]','varchar(max)')
,Pos7 = xDim.value('/x[7]','varchar(max)')
,Pos8 = xDim.value('/x[8]','varchar(max)')
,Pos9 = xDim.value('/x[9]','varchar(max)')
From (Select Cast('<x>' + Replace(@String,'|','</x><x>')+'</x>' as XML) as xDim) A
Returns
Edit - To Use in a Cross Apply - Easy to expand/contract
Declare @YourTable table (ID int,SomeString varchar(max))
Insert Into @YourTable values
(1,'200|50|jo.th@xxx.com|0916|07:00:00'),
(2,'400|99|james.th@xxx.com|1116|09:00:00')
Select A.ID
,B.*
From @YourTable A
Cross Apply (
Select Pos1 = xDim.value('/x[1]','varchar(max)')
,Pos2 = xDim.value('/x[2]','varchar(max)')
,Pos3 = xDim.value('/x[3]','varchar(max)')
,Pos4 = xDim.value('/x[4]','varchar(max)')
,Pos5 = xDim.value('/x[5]','varchar(max)')
,Pos6 = xDim.value('/x[6]','varchar(max)')
,Pos7 = xDim.value('/x[7]','varchar(max)')
,Pos8 = xDim.value('/x[8]','varchar(max)')
,Pos9 = xDim.value('/x[9]','varchar(max)')
From (Select Cast('<x>' + Replace(A.SomeString,'|','</x><x>')+'</x>' as XML) as xDim) A
) B
Returns
我使用以下方法将分隔值放入一组表行中(通常用于在存储过程参数中传递多个值,然后可以将其连接),旋转可以将其转换为列。
(与 SQL Server 2005 及更高版本兼容)
DECLARE @Input varchar(MAX)
DECLARE @Delim char(1)
SET @Input = '200|50|jo.th@xxx.com|0916|07:00:00'
SET @Delim = '|'
DECLARE @VALUES TABLE (ColNo INT, [Param] varchar(MAX))
DECLARE @ChrInd INT
DECLARE @Piece varchar(MAX)
DECLARE @ColNo INT
SET @ColNo = 1
SELECT @ChrInd = 1
WHILE @ChrInd > 0
BEGIN
SELECT @ChrInd = CHARINDEX(@Delim,@Input)
IF @ChrInd > 0
SELECT @Piece = LEFT(@Input,@ChrInd - 1)
ELSE
SELECT @Piece = @Input
INSERT INTO @VALUES(ColNo, [Param]) VALUES(@ColNo, @Piece)
SELECT @Input = RIGHT(@Input,LEN(@Input) - @ChrInd)
IF LEN(@Input) = 0 BREAK
SET @ColNo = @ColNo + 1
END
--SELECT AS ROWS
SELECT * FROM @VALUES
--SELECT AS COLUMNS
SELECT * FROM
(
SELECT ColNo, [Param] FROM @VALUES
) src
PIVOT(
MAX([Param])
FOR ColNo IN ([1],[2],[3],[4],[5])
) AS pvt
结果
ColNo Param
--------------------------------------------------------------------------
1 200
2 50
3 jo.th@xxx.com
4 0916
5 07:00:00
1 2 3 4 5
--------- --------- --------------- ----------- ----------
200 50 jo.th@xxx.com 0916 07:00:00