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