Tsql 将字符串拆分到字典(表)
我有Tsql 将字符串拆分到字典(表),tsql,sql-server-2008-r2,Tsql,Sql Server 2008 R2,我有SplitDictionary功能: ALTER FUNCTION [dbo].[SplitDictionary] ( @RowKey NVARCHAR(MAX), @RowData NVARCHAR(MAX), @Delimeter NVARCHAR(2) ) RETURNS @RtnValue TABLE ( ID INT IDENTITY(1,1), keyValue nvarchar(max), Data NVARCHAR(
SplitDictionary
功能:
ALTER FUNCTION [dbo].[SplitDictionary]
(
@RowKey NVARCHAR(MAX),
@RowData NVARCHAR(MAX),
@Delimeter NVARCHAR(2)
)
RETURNS @RtnValue TABLE
(
ID INT IDENTITY(1,1),
keyValue nvarchar(max),
Data NVARCHAR(MAX)
)
AS
BEGIN
DECLARE @Iterator INT
SET @Iterator = 1
DECLARE @FoundIndex INT
SET @FoundIndex = CHARINDEX(@Delimeter,@RowData)
declare @keyFoundIndex int
set @keyFoundIndex=charindex(@Delimeter, @RowKey)
WHILE (@FoundIndex>0)
BEGIN
INSERT INTO @RtnValue (keyValue, data)
SELECT KeyValue=LTRIM(RTRIM(SUBSTRING(@RowKey, 1, @FoundIndex - 1))),
Data = LTRIM(RTRIM(SUBSTRING(@RowData, 1, @FoundIndex - 1)))
SET @RowKey=substring(@RowKey, @FoundIndex + datalength(@Delimeter)/2, len(@RowKey))
SET @RowData = SUBSTRING(@RowData,@FoundIndex + DATALENGTH(@Delimeter) / 2,LEN(@RowData))
SET @Iterator = @Iterator + 1
SET @FoundIndex = CHARINDEX(@Delimeter, @RowData)
END
INSERT INTO @RtnValue (keyValue, Data)
SELECT keyValue=ltrim(rtrim(@RowKey)), Data = LTRIM(RTRIM(@RowData))
RETURN
END
SELECT ID, keyValue, Data from dbo.SplitDictionary('10,1','20,30', ',')
SELECT ID, keyValue, Data from dbo.SplitDictionary('1,1','20,30', ',')
CREATE FUNCTION dbo.Split (@s varchar(512),@sep char(1))
RETURNS table
AS
RETURN (
WITH Pieces(pn, start, stop) AS (
SELECT 1, 1, CHARINDEX(@sep, @s)
UNION ALL
SELECT pn + 1, stop + 1, CHARINDEX(@sep, @s, stop + 1)
FROM Pieces
WHERE stop > 0
)
SELECT pn,
SUBSTRING(@s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS s
FROM Pieces
)
GO
当我使用此功能时:
ALTER FUNCTION [dbo].[SplitDictionary]
(
@RowKey NVARCHAR(MAX),
@RowData NVARCHAR(MAX),
@Delimeter NVARCHAR(2)
)
RETURNS @RtnValue TABLE
(
ID INT IDENTITY(1,1),
keyValue nvarchar(max),
Data NVARCHAR(MAX)
)
AS
BEGIN
DECLARE @Iterator INT
SET @Iterator = 1
DECLARE @FoundIndex INT
SET @FoundIndex = CHARINDEX(@Delimeter,@RowData)
declare @keyFoundIndex int
set @keyFoundIndex=charindex(@Delimeter, @RowKey)
WHILE (@FoundIndex>0)
BEGIN
INSERT INTO @RtnValue (keyValue, data)
SELECT KeyValue=LTRIM(RTRIM(SUBSTRING(@RowKey, 1, @FoundIndex - 1))),
Data = LTRIM(RTRIM(SUBSTRING(@RowData, 1, @FoundIndex - 1)))
SET @RowKey=substring(@RowKey, @FoundIndex + datalength(@Delimeter)/2, len(@RowKey))
SET @RowData = SUBSTRING(@RowData,@FoundIndex + DATALENGTH(@Delimeter) / 2,LEN(@RowData))
SET @Iterator = @Iterator + 1
SET @FoundIndex = CHARINDEX(@Delimeter, @RowData)
END
INSERT INTO @RtnValue (keyValue, Data)
SELECT keyValue=ltrim(rtrim(@RowKey)), Data = LTRIM(RTRIM(@RowData))
RETURN
END
SELECT ID, keyValue, Data from dbo.SplitDictionary('10,1','20,30', ',')
SELECT ID, keyValue, Data from dbo.SplitDictionary('1,1','20,30', ',')
CREATE FUNCTION dbo.Split (@s varchar(512),@sep char(1))
RETURNS table
AS
RETURN (
WITH Pieces(pn, start, stop) AS (
SELECT 1, 1, CHARINDEX(@sep, @s)
UNION ALL
SELECT pn + 1, stop + 1, CHARINDEX(@sep, @s, stop + 1)
FROM Pieces
WHERE stop > 0
)
SELECT pn,
SUBSTRING(@s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS s
FROM Pieces
)
GO
结果是:
11020 2130 这是真的 当我使用此功能时:
ALTER FUNCTION [dbo].[SplitDictionary]
(
@RowKey NVARCHAR(MAX),
@RowData NVARCHAR(MAX),
@Delimeter NVARCHAR(2)
)
RETURNS @RtnValue TABLE
(
ID INT IDENTITY(1,1),
keyValue nvarchar(max),
Data NVARCHAR(MAX)
)
AS
BEGIN
DECLARE @Iterator INT
SET @Iterator = 1
DECLARE @FoundIndex INT
SET @FoundIndex = CHARINDEX(@Delimeter,@RowData)
declare @keyFoundIndex int
set @keyFoundIndex=charindex(@Delimeter, @RowKey)
WHILE (@FoundIndex>0)
BEGIN
INSERT INTO @RtnValue (keyValue, data)
SELECT KeyValue=LTRIM(RTRIM(SUBSTRING(@RowKey, 1, @FoundIndex - 1))),
Data = LTRIM(RTRIM(SUBSTRING(@RowData, 1, @FoundIndex - 1)))
SET @RowKey=substring(@RowKey, @FoundIndex + datalength(@Delimeter)/2, len(@RowKey))
SET @RowData = SUBSTRING(@RowData,@FoundIndex + DATALENGTH(@Delimeter) / 2,LEN(@RowData))
SET @Iterator = @Iterator + 1
SET @FoundIndex = CHARINDEX(@Delimeter, @RowData)
END
INSERT INTO @RtnValue (keyValue, Data)
SELECT keyValue=ltrim(rtrim(@RowKey)), Data = LTRIM(RTRIM(@RowData))
RETURN
END
SELECT ID, keyValue, Data from dbo.SplitDictionary('10,1','20,30', ',')
SELECT ID, keyValue, Data from dbo.SplitDictionary('1,1','20,30', ',')
CREATE FUNCTION dbo.Split (@s varchar(512),@sep char(1))
RETURNS table
AS
RETURN (
WITH Pieces(pn, start, stop) AS (
SELECT 1, 1, CHARINDEX(@sep, @s)
UNION ALL
SELECT pn + 1, stop + 1, CHARINDEX(@sep, @s, stop + 1)
FROM Pieces
WHERE stop > 0
)
SELECT pn,
SUBSTRING(@s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS s
FROM Pieces
)
GO
结果是:
11,20 2月30日 这是错误的
如何修复存储过程中的第二个调用?这应该可以,请尝试:
ALTER FUNCTION [dbo].[SplitDictionary]
(
@RowKey NVARCHAR(MAX),
@RowData NVARCHAR(MAX),
@Delimeter NVARCHAR(2)
)
RETURNS @RtnValue TABLE
(
ID INT IDENTITY(1,1),
keyValue nvarchar(max),
Data NVARCHAR(MAX)
)
AS
BEGIN
DECLARE @Iterator INT
SET @Iterator = 1
DECLARE @FoundIndex INT
SET @FoundIndex = CHARINDEX(@Delimeter,@RowData)
declare @keyFoundIndex int
set @keyFoundIndex=charindex(@Delimeter, @RowKey)
WHILE (@FoundIndex>0)
BEGIN
INSERT INTO @RtnValue (keyValue, Data)
SELECT KeyValue=LTRIM(RTRIM(SUBSTRING(@RowKey, 1, @keyFoundIndex - 1))),
Data = LTRIM(RTRIM(SUBSTRING(@RowData, 1, @FoundIndex - 1)))
SET @RowKey=substring(@RowKey, @keyFoundIndex + datalength(@Delimeter)/2, len(@RowKey))
SET @RowData = SUBSTRING(@RowData,@FoundIndex + DATALENGTH(@Delimeter) / 2,LEN(@RowData))
SET @Iterator = @Iterator + 1
SET @FoundIndex = CHARINDEX(@Delimeter, @RowData)
SET @keyFoundIndex = CHARINDEX(@Delimeter, @RowKey)
END
INSERT INTO @RtnValue (keyValue, Data)
SELECT keyValue=ltrim(rtrim(@RowKey)), Data = LTRIM(RTRIM(@RowData))
RETURN
END
如果您可以更改输入,使
varchar
遵循以下模式:
'key[0],value[1]:key[1],value[1]:...key[n]:value[n]'
这将使您的varchar
如下所示:
'10,20:1,30'
然后给出这个分割函数:
ALTER FUNCTION [dbo].[SplitDictionary]
(
@RowKey NVARCHAR(MAX),
@RowData NVARCHAR(MAX),
@Delimeter NVARCHAR(2)
)
RETURNS @RtnValue TABLE
(
ID INT IDENTITY(1,1),
keyValue nvarchar(max),
Data NVARCHAR(MAX)
)
AS
BEGIN
DECLARE @Iterator INT
SET @Iterator = 1
DECLARE @FoundIndex INT
SET @FoundIndex = CHARINDEX(@Delimeter,@RowData)
declare @keyFoundIndex int
set @keyFoundIndex=charindex(@Delimeter, @RowKey)
WHILE (@FoundIndex>0)
BEGIN
INSERT INTO @RtnValue (keyValue, data)
SELECT KeyValue=LTRIM(RTRIM(SUBSTRING(@RowKey, 1, @FoundIndex - 1))),
Data = LTRIM(RTRIM(SUBSTRING(@RowData, 1, @FoundIndex - 1)))
SET @RowKey=substring(@RowKey, @FoundIndex + datalength(@Delimeter)/2, len(@RowKey))
SET @RowData = SUBSTRING(@RowData,@FoundIndex + DATALENGTH(@Delimeter) / 2,LEN(@RowData))
SET @Iterator = @Iterator + 1
SET @FoundIndex = CHARINDEX(@Delimeter, @RowData)
END
INSERT INTO @RtnValue (keyValue, Data)
SELECT keyValue=ltrim(rtrim(@RowKey)), Data = LTRIM(RTRIM(@RowData))
RETURN
END
SELECT ID, keyValue, Data from dbo.SplitDictionary('10,1','20,30', ',')
SELECT ID, keyValue, Data from dbo.SplitDictionary('1,1','20,30', ',')
CREATE FUNCTION dbo.Split (@s varchar(512),@sep char(1))
RETURNS table
AS
RETURN (
WITH Pieces(pn, start, stop) AS (
SELECT 1, 1, CHARINDEX(@sep, @s)
UNION ALL
SELECT pn + 1, stop + 1, CHARINDEX(@sep, @s, stop + 1)
FROM Pieces
WHERE stop > 0
)
SELECT pn,
SUBSTRING(@s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS s
FROM Pieces
)
GO
您的sql查询非常简单。像这样:
DECLARE @varcharToSplit VARCHAR(512)
SET @varcharToSplit='10,20:1,30'
SELECT
pvt.RowIndex,
pvt.[1] AS [Key],
pvt.[2] AS Value
FROM
(
SELECT
SplitColumns.pn AS ColumnIndex,
SplitColumns.s AS ColumnValue,
SplitRows.pn AS RowIndex
FROM
dbo.Split(@varcharToSplit,':') AS SplitRows
CROSS APPLY dbo.Split(SplitRows.s,',') AS SplitColumns
) AS SourceTable
PIVOT
(
MAX(ColumnValue)
FOR ColumnIndex IN ([1],[2])
) AS pvt