2017-03-18 11 views
1

私は、文字列を持っている私が試しましたしかし、私はそれが性能だとは思わない。SQL Serverの分割使用してテーブルに文字列が

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' 
+0

使用しているSQLのバージョンは何ですか?まだ何か試してみましたか?あるいは、この問題についてグーグルで試してみましたか? –

+0

私は試しましたが、私はそれがパフォーマンスだとは思わない –

答えて

1

ジェフ・モデンウィットによるCSVスプリッタテーブル値関数を使うH cross apply()

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 | 
+-------------+------+ 

分割ストリングが参照:

+0

Plus1 replace()がクロスアプリケーションを排除するのを見ていませんでした –

0

私はあなたがこの目的のために(C#の場合)CLR機能を備えた最高のパフォーマンスを得るべきだと思う:

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

手動で入力を分割したり、作成することがあります名前付きグループを持つRegexをコンパイルして入力値を解析します。

関連する問題