sql >> Databáze >  >> RDS >> Sqlserver

Jak vybrat vnořený JSON v SQL Server s OPENJSON

Pokud používáte OPENJSON() , ale snažíte se zapamatovat si, jak vybrat vnitřní fragment z dokumentu JSON, čtěte dále.

OPENJSON() syntaxe umožňuje převádět dokumenty JSON do tabulkového zobrazení. Umožňuje vám také vybrat vnořený fragment JSON z dokumentu JSON.

Způsob, jak toho dosáhnout, je pomocí cest .

Cesty

Cesta se skládá z následujícího:

  • Znak dolaru ($ ), která představuje kontextovou položku.
  • Sada kroků cesty. Kroky cesty mohou obsahovat následující prvky a operátory:
    • Jména klíčů. Například $.pets a $.pets.dogs . Pokud název klíče začíná znakem dolaru nebo obsahuje speciální znaky, jako jsou mezery, musí být obklopen uvozovkami (například $."my pets" ).
    • Prvky pole. Například $.pets.dogs[1] . Indexy pole jsou založeny na nule, takže tento příklad vybere druhý prvek v poli.
    • Tečkový operátor (. ) označuje člena objektu. Například v $.pets.dogs , dogs je členem pets .

Základní příklad

Zde je jednoduchý příklad k demonstraci.

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)
    );

Výsledek:

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

V tomto případě druhý argument pro OPENJSON() je '$.pets.dogs' , což znamená, že vybíráme hodnotu dogs klíč, který je sám o sobě potomkem pets .

Znak dolaru ($ ) představuje kontextovou položku.

Všimněte si, že v tomto příkladu také používám WITH klauzule k definování schématu. Pokud bych to nezahrnul, místo toho by se použilo výchozí schéma.

Zde je návod, jak to vypadá s použitím výchozího schématu.

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');

Výsledek:

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

Stále tedy vybíráme stejný vnořený JSON, jen používáme jiné schéma.

Výchozí schéma vždy vrací tři sloupce; klíč , hodnota a zadejte .

Výběr prvků pole

Jak již bylo zmíněno, k výběru konkrétního prvku v poli můžete použít notaci hranatých závorek.

Zde je příklad.

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)
    );

Výsledek:

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

Indexy pole jsou založeny na nule a uvádějí hodnotu 0 vrátí první prvek v poli.

Takto vypadá tento příklad při použití výchozího schématu (tj. bez WITH doložka).

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]');

Výsledek:

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

Režim cesty

Při použití cest máte možnost deklarovat režim cesty.

Režim cesty určuje, co se stane, když výraz cesty obsahuje chybu.

Režim cesty může být buď lax nebo strict .

  • V lax režimu, funkce vrátí prázdné hodnoty, pokud cestu nelze najít. Pokud například požadujete hodnotu $.pets.cows , ale JSON tento klíč neobsahuje, funkce vrátí hodnotu null, ale nevyvolá chybu.
  • V strict režimu, funkce vyvolá chybu, pokud cestu nelze najít.

Výchozí režim cesty je lax , takže pokud to nedeklarujete, lax se používá.

Příklad

Zde je příklad demonstrující, jak každý režim cesty zpracovává chybějící cesty.

Laxní režim

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');

Výsledek:

(0 rows affected)

Laxní režim tedy nevyvolal žádné chyby. Jednoduše to vedlo k ovlivnění nula řádků.

Pokud bychom zadali vlastní schéma a vybrali správný dílčí objekt, ale použili jsme chybějící cestu k mapování na název sloupce, vrátilo by to NULL v tomto sloupci.

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'
    );

Výsledek:

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

Přísný režim

Zde je to, co se stane, když použijeme přísný režim.

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');

Výsledek:

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

Podle očekávání došlo k chybě.

Ke stejné chybě dojde, když vybereme správný klíč JSON, ale namapujeme sloupec na neexistující klíč.

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'
    );

Výsledek:

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

Duplicitní cesty

Pokud váš dokument JSON obsahuje duplicitní cesty na stejné úrovni vnoření, OPENJSON() může je všechny vrátit.

To je v kontrastu s JSON_VALUE() a JSON_QUERY() , obě vracejí pouze první hodnotu, která odpovídá cestě.

Zde je příklad použití OPENJSON() vrátit duplicitní cesty.

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

Výsledek:

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

Vnořené dílčí objekty

Při definování vlastního schématu můžete použít AS JSON možnost vrátit celý dílčí objekt jako svůj vlastní dokument 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
    );

Výsledek:

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

Pokud bychom nepoužili AS JSON možnost, dostali bychom chybu nebo NULL, v závislosti na tom, zda jsme zadali lax nebo strict režimu.

Zde je v každém režimu při vynechání AS JSON možnost.

Laxní režim

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'
    );

Výsledek:

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

Přísný režim

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'
    );

Výsledek:

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

  1. Jak převést řetězec na malá písmena v SQL

  2. OracleDataSource vs. Oracle UCP PoolDataSource

  3. SQL Server ALL operátor vysvětlen

  4. mysql SQL:konkrétní položka, která má být první, a potom seřadit zbývající položky