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

OPENJSONを使用してSQLServerでネストされたJSONを選択する方法

    OPENJSON()を使用している場合 、しかし、JSONドキュメントから内部フラグメントを選択する方法を思い出そうとしているので、読み進めてください。

    OPENJSON() 構文を使用すると、JSONドキュメントを表形式のビューに変換できます。また、JSONドキュメントからネストされたJSONフラグメントを選択することもできます。

    これを行う方法は、パスを使用することです。 。

    パス

    パスは次のもので構成されます:

    • ドル記号($ )、これはコンテキストアイテムを表します。
    • 一連のパスステップ。パスステップには、次の要素と演算子を含めることができます。
      • キー名。例:$.pets および$.pets.dogs 。キー名がドル記号で始まる場合、またはスペースなどの特殊文字が含まれている場合は、引用符で囲む必要があります(たとえば、 $."my pets"
      • 配列要素。例:$.pets.dogs[1] 。配列インデックスはゼロベースであるため、この例では配列の2番目の要素を選択します。
      • ドット演算子(. )はオブジェクトのメンバーを示します。たとえば、$.pets.dogsdogs petsのメンバーです 。

    基本的な例

    簡単な例を次に示します。

    DECLARE @json NVARCHAR(4000) = N'{ 
        "pets" : {
                "cats" : [
                { "id" : 1, "name" : "Fluffy", "sex" : "Female" },
                { "id" : 2, "name" : "Long Tail", "sex" : "Female" },
                { "id" : 3, "name" : "Scratch", "sex" : "Male" }
            ],
                "dogs" : [
                { "id" : 1, "name" : "Fetch", "sex" : "Male" },
                { "id" : 2, "name" : "Fluffy", "sex" : "Male" },
                { "id" : 3, "name" : "Wag", "sex" : "Female" }
            ]
        }
    }';
    
    SELECT *
    FROM OPENJSON(@json, '$.pets.dogs')
    WITH  (
            [id]    int,  
            [name]  varchar(60), 
            [sex]   varchar(6)
        );

    結果:

    +------+--------+--------+
    | id   | name   | sex    |
    |------+--------+--------|
    | 1    | Fetch  | Male   |
    | 2    | Fluffy | Male   |
    | 3    | Wag    | Female |
    +------+--------+--------+

    この場合、OPENJSON()の2番目の引数 は'$.pets.dogs' 、これは、dogsの値を選択していることを意味します キー、それ自体はpetsの子です 。

    ドル記号($ )はコンテキストアイテムを表します。

    この例では、WITHも使用していることに注意してください。 スキーマを定義する句。これを含めなかった場合は、代わりにデフォルトのスキーマが使用されます。

    デフォルトのスキーマを使用した場合の外観は次のとおりです。

    DECLARE @json NVARCHAR(4000) = N'{ 
        "pets" : {
                "cats" : [
                { "id" : 1, "name" : "Fluffy", "sex" : "Female" },
                { "id" : 2, "name" : "Long Tail", "sex" : "Female" },
                { "id" : 3, "name" : "Scratch", "sex" : "Male" }
            ],
                "dogs" : [
                { "id" : 1, "name" : "Fetch", "sex" : "Male" },
                { "id" : 2, "name" : "Fluffy", "sex" : "Male" },
                { "id" : 3, "name" : "Wag", "sex" : "Female" }
            ]
        }
    }';
    
    SELECT *
    FROM OPENJSON(@json, '$.pets.dogs');

    結果:

    +-------+-------------------------------------------------+--------+
    | key   | value                                           | type   |
    |-------+-------------------------------------------------+--------|
    | 0     | { "id" : 1, "name" : "Fetch", "sex" : "Male" }  | 5      |
    | 1     | { "id" : 2, "name" : "Fluffy", "sex" : "Male" } | 5      |
    | 2     | { "id" : 3, "name" : "Wag", "sex" : "Female" }  | 5      |
    +-------+-------------------------------------------------+--------+

    そのため、同じネストされたJSONを引き続き選択しています。これは、別のスキーマを使用しているだけです。

    デフォルトのスキーマは常に3つの列を返します。 キー 、およびタイプ

    配列要素の選択

    前述のように、角括弧表記を使用して、配列内の特定の要素を選択できます。

    これが例です。

    DECLARE @json NVARCHAR(4000) = N'{ 
        "pets" : {
                "cats" : [
                { "id" : 1, "name" : "Fluffy", "sex" : "Female" },
                { "id" : 2, "name" : "Long Tail", "sex" : "Female" },
                { "id" : 3, "name" : "Scratch", "sex" : "Male" }
            ],
                "dogs" : [
                { "id" : 1, "name" : "Fetch", "sex" : "Male" },
                { "id" : 2, "name" : "Fluffy", "sex" : "Male" },
                { "id" : 3, "name" : "Wag", "sex" : "Female" }
            ]
        }
    }';
    
    SELECT *
    FROM OPENJSON(@json, '$.pets.dogs[0]')
    WITH  (
            [id]    int,  
            [name]  varchar(60), 
            [sex]   varchar(6)
        );

    結果:

    +------+--------+-------+
    | id   | name   | sex   |
    |------+--------+-------|
    | 1    | Fetch  | Male  |
    +------+--------+-------+

    配列インデックスはゼロベースであるため、0の値を指定します 配列の最初の要素を返します。

    デフォルトのスキーマを使用した場合(つまり、WITHを使用しない場合のこの例は次のようになります。 条項)。

    DECLARE @json NVARCHAR(4000) = N'{ 
        "pets" : {
                "cats" : [
                { "id" : 1, "name" : "Fluffy", "sex" : "Female" },
                { "id" : 2, "name" : "Long Tail", "sex" : "Female" },
                { "id" : 3, "name" : "Scratch", "sex" : "Male" }
            ],
                "dogs" : [
                { "id" : 1, "name" : "Fetch", "sex" : "Male" },
                { "id" : 2, "name" : "Fluffy", "sex" : "Male" },
                { "id" : 3, "name" : "Wag", "sex" : "Female" }
            ]
        }
    }';
    
    SELECT *
    FROM OPENJSON(@json, '$.pets.dogs[0]');

    結果:

    +-------+---------+--------+
    | key   | value   | type   |
    |-------+---------+--------|
    | id    | 1       | 2      |
    | name  | Fetch   | 1      |
    | sex   | Male    | 1      |
    +-------+---------+--------+

    パスモード

    パスを使用する場合、パスモードを宣言するオプションがあります。

    パスモードは、パス式にエラーが含まれている場合に何が起こるかを決定します。

    パスモードは、laxのいずれかになります。 またはstrict

    • laxで モードの場合、パスが見つからない場合、関数は空の値を返します。たとえば、値$.pets.cowsをリクエストした場合 、ただしJSONにそのキーが含まれていない場合、関数はnullを返しますが、エラーは発生しません。
    • strictで モードの場合、パスが見つからない場合、関数はエラーを発生させます。

    デフォルトのパスモードはlaxです 、したがって、宣言しない場合は、lax 使用されている。

    各パスモードが欠落しているパスを処理する方法を示す例を次に示します。

    ラックスモード

    DECLARE @json NVARCHAR(4000) = N'{ 
        "pets" : {
                "cats" : [
                { "id" : 1, "name" : "Fluffy", "sex" : "Female" },
                { "id" : 2, "name" : "Long Tail", "sex" : "Female" },
                { "id" : 3, "name" : "Scratch", "sex" : "Male" }
            ],
                "dogs" : [
                { "id" : 1, "name" : "Fetch", "sex" : "Male" },
                { "id" : 2, "name" : "Fluffy", "sex" : "Male" },
                { "id" : 3, "name" : "Wag", "sex" : "Female" }
            ]
        }
    }';
    
    SELECT *
    FROM OPENJSON(@json, 'lax $.pets.cows');

    結果:

    (0 rows affected)

    したがって、緩いモードではエラーは発生しませんでした。影響を受ける行がゼロになるだけです。

    独自のスキーマを指定し、正しいサブオブジェクトを選択したが、欠落しているパスを使用して列名にマップした場合、NULLが返されます。 その列にあります。

    DECLARE @json NVARCHAR(4000) = N'{ 
        "pets" : {
                "cats" : [
                { "id" : 1, "name" : "Fluffy", "sex" : "Female" },
                { "id" : 2, "name" : "Long Tail", "sex" : "Female" },
                { "id" : 3, "name" : "Scratch", "sex" : "Male" }
            ],
                "dogs" : [
                { "id" : 1, "name" : "Fetch", "sex" : "Male" },
                { "id" : 2, "name" : "Fluffy", "sex" : "Male" },
                { "id" : 3, "name" : "Wag", "sex" : "Female" }
            ]
        }
    }'
    
    SELECT *
    FROM OPENJSON(@json, 'lax $.pets.dogs')
    WITH  (
            [id]    int         'lax $.id',  
            [name]  varchar(60) 'lax $.name', 
            [color]   varchar(6)  'lax $.color'
        );

    結果:

    +------+--------+---------+
    | id   | name   | color   |
    |------+--------+---------|
    | 1    | Fetch  | NULL    |
    | 2    | Fluffy | NULL    |
    | 3    | Wag    | NULL    |
    +------+--------+---------+

    厳密モード

    厳密モードを使用すると、次のようになります。

    DECLARE @json NVARCHAR(4000) = N'{ 
        "pets" : {
                "cats" : [
                { "id" : 1, "name" : "Fluffy", "sex" : "Female" },
                { "id" : 2, "name" : "Long Tail", "sex" : "Female" },
                { "id" : 3, "name" : "Scratch", "sex" : "Male" }
            ],
                "dogs" : [
                { "id" : 1, "name" : "Fetch", "sex" : "Male" },
                { "id" : 2, "name" : "Fluffy", "sex" : "Male" },
                { "id" : 3, "name" : "Wag", "sex" : "Female" }
            ]
        }
    }';
    
    SELECT *
    FROM OPENJSON(@json, 'strict $.pets.cows');

    結果:

    Msg 13608, Level 16, State 3, Line 16
    Property cannot be found on the specified JSON path.

    予想どおり、エラーが発生しました。

    正しいJSONキーを選択しても同じエラーが発生しますが、列を存在しないキーにマップします。

    DECLARE @json NVARCHAR(4000) = N'{ 
        "pets" : {
                "cats" : [
                { "id" : 1, "name" : "Fluffy", "sex" : "Female" },
                { "id" : 2, "name" : "Long Tail", "sex" : "Female" },
                { "id" : 3, "name" : "Scratch", "sex" : "Male" }
            ],
                "dogs" : [
                { "id" : 1, "name" : "Fetch", "sex" : "Male" },
                { "id" : 2, "name" : "Fluffy", "sex" : "Male" },
                { "id" : 3, "name" : "Wag", "sex" : "Female" }
            ]
        }
    }';
    
    SELECT *
    FROM OPENJSON(@json, 'strict $.pets.dogs')
    WITH  (
            [id]    int         'strict $.id',  
            [name]  varchar(60) 'strict $.name', 
            [color]   varchar(6)  'strict $.color'
        );

    結果:

    Msg 13608, Level 16, State 6, Line 16
    Property cannot be found on the specified JSON path.

    重複パス

    JSONドキュメントに同じネストレベルで重複するパスが含まれている場合は、OPENJSON() それらすべてを返すことができます。

    これは、JSON_VALUE()とは対照的です。 およびJSON_QUERY() 、どちらもパスに一致する最初の値のみを返します。

    OPENJSON()の使用例を次に示します。 重複するパスを返します。

    DECLARE @json NVARCHAR(4000) = N'{
        "dog": {
                "names": {
                    "name": "Fetch", 
                    "name": "Good Dog"
                }
            }
        }';
    SELECT * FROM OPENJSON(@json, '$.dog.names');

    結果:

    +-------+----------+--------+
    | key   | value    | type   |
    |-------+----------+--------|
    | name  | Fetch    | 1      |
    | name  | Good Dog | 1      |
    +-------+----------+--------+

    ネストされたサブオブジェクト

    独自のスキーマを定義する場合は、AS JSONを使用できます サブオブジェクト全体を独自のJSONドキュメントとして返すオプション。

    DECLARE @json NVARCHAR(4000) = N'{ 
        "pets" : {
                "cats" : [
                { "id" : 1, "name" : "Fluffy", "sex" : "Female" },
                { "id" : 2, "name" : "Long Tail", "sex" : "Female" },
                { "id" : 3, "name" : "Scratch", "sex" : "Male" }
            ],
                "dogs" : [
                { "id" : 1, "name" : "Fetch", "sex" : "Male" },
                { "id" : 2, "name" : "Fluffy", "sex" : "Male" },
                { "id" : 3, "name" : "Wag", "sex" : "Female" }
            ]
        }
    }';
    
    SELECT *
    FROM OPENJSON(@json, '$.pets')
    WITH  (
            [dogs]  nvarchar(max) '$.dogs' AS JSON
        );

    結果:

    +--------+
    | dogs   |
    |--------|
    | [
                { "id" : 1, "name" : "Fetch", "sex" : "Male" },
                { "id" : 2, "name" : "Fluffy", "sex" : "Male" },
                { "id" : 3, "name" : "Wag", "sex" : "Female" }
            ]        |
    +--------+

    AS JSONを使用していなかった場合 オプションの場合、laxを指定したかどうかに応じて、エラーまたはNULLを受け取ります。 またはstrict モード。

    ここでは、AS JSONを省略した場合の各モードになります オプション。

    ラックスモード

    DECLARE @json NVARCHAR(4000) = N'{ 
        "pets" : {
                "cats" : [
                { "id" : 1, "name" : "Fluffy", "sex" : "Female" },
                { "id" : 2, "name" : "Long Tail", "sex" : "Female" },
                { "id" : 3, "name" : "Scratch", "sex" : "Male" }
            ],
                "dogs" : [
                { "id" : 1, "name" : "Fetch", "sex" : "Male" },
                { "id" : 2, "name" : "Fluffy", "sex" : "Male" },
                { "id" : 3, "name" : "Wag", "sex" : "Female" }
            ]
        }
    }';
    
    SELECT *
    FROM OPENJSON(@json, '$.pets')
    WITH  (
            [dogs]  nvarchar(max) 'lax $.dogs'
        );

    結果:

    +--------+
    | dogs   |
    |--------|
    | NULL   |
    +--------+

    厳密モード

    DECLARE @json NVARCHAR(4000) = N'{ 
        "pets" : {
                "cats" : [
                { "id" : 1, "name" : "Fluffy", "sex" : "Female" },
                { "id" : 2, "name" : "Long Tail", "sex" : "Female" },
                { "id" : 3, "name" : "Scratch", "sex" : "Male" }
            ],
                "dogs" : [
                { "id" : 1, "name" : "Fetch", "sex" : "Male" },
                { "id" : 2, "name" : "Fluffy", "sex" : "Male" },
                { "id" : 3, "name" : "Wag", "sex" : "Female" }
            ]
        }
    }';
    
    SELECT *
    FROM OPENJSON(@json, '$.pets')
    WITH  (
            [dogs]  nvarchar(max) 'strict $.dogs'
        );

    結果:

    Msg 13624, Level 16, State 1, Line 16
    Object or array cannot be found in the specified JSON path.

    1. oracle PL / SQLIPv6cidrの範囲IPを計算する方法

    2. MariaDBでデータベースの文字セットと照合を設定する

    3. コマンドライン引数を使用してPostgreSQL.sqlファイルを実行します

    4. MyBatisRowBoundsはクエリ結果を制限しません