sql >> データベース >  >> RDS >> Sqlserver

T-SQLを使用して、文字列からn番目に区切られた要素を返します

    これは、67を救済するための最も簡単な答えです(タイプセーフ!! ):

    SELECT CAST('<x>' + REPLACE('1,222,2,67,888,1111',',','</x><x>') + '</x>' AS XML).value('/x[4]','int')
    

    以下に、文字列、区切り文字、および位置の変数でこれを使用する方法の例を示します(XMLで禁止されている文字を含むエッジケースの場合でも)

    簡単なもの

    この質問は文字列分割アプローチに関するものではありません 、ただし、n番目の要素を取得する方法について 。最も簡単で完全にインライン化できない方法は、このIMOです:

    これは本物のワンライナーです スペースで区切られたパート2を取得するには:

    DECLARE @input NVARCHAR(100)=N'part1 part2 part3';
    SELECT CAST(N'<x>' + REPLACE(@input,N' ',N'</x><x>') + N'</x>' AS XML).value('/x[2]','nvarchar(max)')
    

    変数はsql:variable()で使用できます またはsql:column()

    もちろん、変数を使用できます 区切り文字と位置(sql:columnを使用) クエリの値から直接位置を取得するには):

    DECLARE @dlmt NVARCHAR(10)=N' ';
    DECLARE @pos INT = 2;
    SELECT CAST(N'<x>' + REPLACE(@input,@dlmt,N'</x><x>') + N'</x>' AS XML).value('/x[sql:variable("@pos")][1]','nvarchar(max)')
    

    XMLで禁止されている文字を使用したエッジケース

    文字列に禁止文字が含まれている可能性がある場合 、あなたはまだこの方法でそれを行うことができます。 FOR XML PATHを使用するだけです 最初に文字列で禁止されているすべての文字を、暗黙的に適切なエスケープシーケンスに置き換えます。

    -さらに-区切り文字がセミコロンである場合は、非常に特殊なケースです。 。この場合、最初に区切り文字を「#DLMT#」に置き換え、最後にこれをXMLタグに置き換えます。

    SET @input=N'Some <, > and &;Other äöü@€;One more';
    SET @dlmt=N';';
    SELECT CAST(N'<x>' + REPLACE((SELECT REPLACE(@input,@dlmt,'#DLMT#') AS [*] FOR XML PATH('')),N'#DLMT#',N'</x><x>') + N'</x>' AS XML).value('/x[sql:variable("@pos")][1]','nvarchar(max)');
    

    SQL-Server2016以降の更新

    残念ながら、開発者はSTRING_SPLITでパーツのインデックスを返すのを忘れていました 。ただし、SQL-Server 2016以降を使用すると、JSON_VALUEがあります。 およびOPENJSON

    JSON_VALUEを使用 インデックスの配列としてその位置を渡すことができます。

    OPENJSONの場合 ドキュメントには明確に記載されています:

    OPENJSONがJSON配列を解析するとき、関数はJSONテキスト内の要素のインデックスをキーとして返します。

    1,2,3のような文字列 角かっこだけが必要です:[1,2,3]
    this is an exampleのような単語の文字列 ["this","is","an"," example"]である必要があります 。
    これらは非常に簡単な文字列操作です。試してみてください:

    DECLARE @str VARCHAR(100)='Hello John Smith';
    DECLARE @position INT = 2;
    
    --We can build the json-path '$[1]' using CONCAT
    SELECT JSON_VALUE('["' + REPLACE(@str,' ','","') + '"]',CONCAT('$[',@position-1,']'));
    

    -位置に安全な文字列スプリッター(ゼロベース)については、こちらをご覧ください ):

    SELECT  JsonArray.[key] AS [Position]
           ,JsonArray.[value] AS [Part]
    FROM OPENJSON('["' + REPLACE(@str,' ','","') + '"]') JsonArray
    

    この投稿では、さまざまなアプローチをテストし、そのOPENJSON 本当に速いです。有名な「delimitedSplit8k()」メソッドよりもはるかに高速です...

    UPDATE2-値をタイプセーフに取得

    配列内の配列を使用できます 2倍の[[]]を使用するだけです 。これにより、入力されたWITHが可能になります -条項:

    DECLARE  @SomeDelimitedString VARCHAR(100)='part1|1|20190920';
    
    DECLARE @JsonArray NVARCHAR(MAX)=CONCAT('[["',REPLACE(@SomeDelimitedString,'|','","'),'"]]');
    
    SELECT @SomeDelimitedString          AS TheOriginal
          ,@JsonArray                    AS TransformedToJSON
          ,ValuesFromTheArray.*
    FROM OPENJSON(@JsonArray)
    WITH(TheFirstFragment VARCHAR(100) '$[0]'
        ,TheSecondFragment INT '$[1]'
        ,TheThirdFragment DATE '$[2]') ValuesFromTheArray
    


    1. MySQL –ドロップされたパフォーマンススキーマデータベースを回復する

    2. Oracleポートをポート8080から変更します

    3. SQLiteにデータを挿入するときに、NULL値を列のデフォルト値に変換する

    4. 時間が経過した後にmysql行を削除する方法は?