Sql Server使用将字符串拆分为表

时间:2017-03-18 11:45:59

标签: sql

我有一个字符串:Brand=b1-b2&Vendor=v1-v2-v3&CustomField=cf1-cf2-cf3

我想做一张桌子..

**Name**      | **Value**
------------- | ------
Brand         | b1
Brand         | b2
Vendor        | v1
Vendor        | v2
Vendor        | v3
CustomField   | cf1
CustomField   | cf2
CustomField   | cf3

感谢您的帮助

编辑注意:我试过,但我不认为这是性能

CREATE PROCEDURE [dbo].[SplitTableInStr]
(
    @StrParameter NVARCHAR(MAX)
)
AS
BEGIN
    DECLARE @Delimiter CHAR = '&',
            @Index SMALLINT,
            @Start SMALLINT,
            @DelSize SMALLINT;

    SET @DelSize = LEN(@Delimiter);

    CREATE TABLE #FilteredItems
    (
        [Key] NVARCHAR(400),
        [Values] NVARCHAR(MAX)
    )

    WHILE LEN(@StrParameter) > 0
    BEGIN
        SET @Index = CHARINDEX(@Delimiter, @StrParameter)
        IF @Index = 0
            BEGIN
                DECLARE @Key NVARCHAR(400) = SUBSTRING(@StrParameter, 1, CHARINDEX('=', @StrParameter) - 1);
                DECLARE @Values NVARCHAR(MAX) = SUBSTRING(@StrParameter, CHARINDEX('=', @StrParameter) + 1, LEN(@StrParameter));

                INSERT INTO #FilteredItems ([Key],[Values])
                VALUES (@Key,@Values) 
                BREAK
            END
        ELSE
            BEGIN
                DECLARE @IndexItem NVARCHAR(MAX) = SUBSTRING(@StrParameter, 1, @Index - 1);

                DECLARE @IndexKey NVARCHAR(400) = SUBSTRING(@IndexItem, 1, CHARINDEX('=', @IndexItem) - 1);
                DECLARE @IndexValues NVARCHAR(MAX) = SUBSTRING(@IndexItem, CHARINDEX('=', @IndexItem) + 1, LEN(@IndexItem));

                INSERT INTO #FilteredItems ([Key],[Values])
                VALUES (@IndexKey,@IndexValues)

                SET @Start = @Index + @DelSize
                SET @StrParameter = SUBSTRING(@StrParameter, @Start , LEN(@StrParameter) - @Start + 1)
            END
    END

    DECLARE @KeyBase NVARCHAR(400),
            @ValueBase NVARCHAR(MAX);

    CREATE TABLE #DisplayOrderTmp 
    (
        [EndName] NVARCHAR(400),
        [EndValue] NVARCHAR(400)
    )

    WHILE EXISTS(SELECT * From #FilteredItems)
    BEGIN
        SELECT TOP 1 @KeyBase = [Key], @ValueBase = [Values] FROM #FilteredItems

        DECLARE @OptionDelimiter CHAR = '-',
                @OptionIndex SMALLINT,
                @OptionStart SMALLINT,
                @OptionDelSize SMALLINT;

        SET @OptionDelSize = LEN(@OptionDelimiter)

        WHILE LEN(@ValueBase) > 0
        BEGIN
            SET @OptionIndex = CHARINDEX(@OptionDelimiter, @ValueBase)

            IF @OptionIndex = 0
                BEGIN
                    INSERT INTO #DisplayOrderTmp VALUES (@KeyBase, @ValueBase)
                    BREAK;
                END
            ELSE
                BEGIN
                    INSERT INTO #DisplayOrderTmp VALUES (@KeyBase, SUBSTRING(@ValueBase, 1, CHARINDEX(@OptionDelimiter, @ValueBase) - 1))

                    SET @OptionStart = @OptionIndex + @OptionDelSize
                    SET @ValueBase = SUBSTRING(@ValueBase, @OptionStart , LEN(@ValueBase) - @OptionStart + 1)
                END
        END

        DELETE #FilteredItems WHERE [Key] = @KeyBase
    END

    SELECT * FROM #DisplayOrderTmp;
END

EXEC dbo.[SplitTableInStr] 'Brand=b1-b2&Vendor=v1-v2-v3&CustomField=cf1-cf2-cf3'

2 个答案:

答案 0 :(得分:1)

使用带有cross apply()

的Jeff Moden的CSV Splitter表值函数
declare @s nvarchar(4000) = 'Brand=b1-b2&Vendor=v1-v2-v3&CustomField=cf1-cf2-cf3';
select 
    Name = left(s.Item,charindex('=',s.Item)-1)
  , Value = i.Item
from dbo.DelimitedSplitN4k(@s,'&') s
  cross apply dbo.DelimitedSplitN4k(replace(s.Item,'=','-'),'-') i
where i.ItemNumber > 1

rextester演示:http://rextester.com/RTAT28301

返回:

+-------------+------+
|    Name     | Item |
+-------------+------+
| Brand       | b1   |
| Brand       | b2   |
| Vendor      | v1   |
| Vendor      | v2   |
| Vendor      | v3   |
| CustomField | cf1  |
| CustomField | cf2  |
| CustomField | cf3  |
+-------------+------+

拆分字符串参考:

答案 1 :(得分:0)

我认为你应该用CLR功能(在C#中)获得最佳性能:

https://msdn.microsoft.com/en-us/library/ms131103.aspx

您可以手动拆分输入或使用命名组创建已编译的Regex来解析输入值。