Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Cara Memilih JSON Bersarang di SQL Server dengan OPENJSON

Jika Anda menggunakan OPENJSON() , tetapi Anda mencoba mengingat cara memilih fragmen bagian dalam dari dokumen JSON, baca terus.

OPENJSON() sintaks memungkinkan Anda untuk mengubah dokumen JSON menjadi tampilan tabel. Ini juga memungkinkan Anda untuk memilih fragmen JSON bersarang dari dokumen JSON.

Cara melakukannya adalah dengan jalur .

Jalur

Jalur terdiri dari berikut ini:

  • Tanda dolar ($ ), yang mewakili item konteks.
  • Satu set langkah-langkah jalur. Langkah-langkah jalur dapat berisi elemen dan operator berikut:
    • Nama-nama kunci. Misalnya, $.pets dan $.pets.dogs . Jika nama kunci dimulai dengan tanda dolar atau berisi karakter khusus seperti spasi, nama kunci harus diapit dengan tanda kutip (misalnya $."my pets" ).
    • Elemen larik. Misalnya, $.pets.dogs[1] . Indeks larik berbasis nol, jadi contoh ini memilih elemen kedua dalam larik.
    • Operator titik (. ) menunjukkan anggota suatu objek. Misalnya, di $.pets.dogs , dogs adalah anggota pets .

Contoh Dasar

Berikut adalah contoh sederhana untuk didemonstrasikan.

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

Hasil:

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

Dalam hal ini, argumen kedua untuk OPENJSON() adalah '$.pets.dogs' , yang berarti kita memilih nilai dogs key, yang merupakan anak dari pets .

Tanda dolar ($ ) mewakili item konteks.

Perhatikan bahwa dalam contoh ini, saya juga menggunakan WITH klausa untuk mendefinisikan skema. Jika saya tidak menyertakan itu, skema default akan digunakan sebagai gantinya.

Berikut tampilannya menggunakan skema default.

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

Hasil:

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

Jadi kita masih memilih nested JSON yang sama, hanya saja kita menggunakan skema yang berbeda.

Skema default selalu mengembalikan tiga kolom; kunci , nilai , dan ketik .

Memilih Elemen Array

Seperti yang disebutkan, Anda dapat menggunakan notasi kurung siku untuk memilih elemen tertentu dalam array.

Ini contohnya.

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

Hasil:

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

Melihat indeks array berbasis nol, menetapkan nilai 0 mengembalikan elemen pertama dalam larik.

Berikut adalah tampilan contoh ini saat menggunakan skema default (yaitu tanpa WITH klausa).

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

Hasil:

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

Mode Jalur

Saat menggunakan jalur, Anda memiliki opsi untuk mendeklarasikan mode jalur.

Mode jalur menentukan apa yang terjadi ketika ekspresi jalur berisi kesalahan.

Mode jalur dapat berupa lax atau strict .

  • Dalam lax mode, fungsi mengembalikan nilai kosong jika jalur tidak dapat ditemukan. Misalnya, jika Anda meminta nilai $.pets.cows , tetapi JSON tidak berisi kunci itu, fungsi mengembalikan null, tetapi tidak menimbulkan kesalahan.
  • Dalam strict mode, fungsi memunculkan kesalahan jika jalur tidak dapat ditemukan.

Mode jalur default adalah lax , jadi jika Anda tidak mendeklarasikannya, lax digunakan.

Contoh

Berikut adalah contoh untuk menunjukkan bagaimana setiap mode jalur menangani jalur yang hilang.

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

Hasil:

(0 rows affected)

Jadi mode longgar tidak menimbulkan kesalahan apa pun. Itu hanya mengakibatkan nol baris terpengaruh.

Jika kami menentukan skema kami sendiri, dan kami memilih sub-objek yang benar, tetapi kami menggunakan jalur yang hilang untuk memetakan ke nama kolom, itu akan mengembalikan NULL di kolom itu.

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

Hasil:

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

Mode Ketat

Inilah yang terjadi jika kita menggunakan mode ketat.

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

Hasil:

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

Seperti yang diharapkan, ini menghasilkan kesalahan.

Kesalahan yang sama terjadi saat kami memilih kunci JSON yang benar, tetapi memetakan kolom ke kunci yang tidak ada.

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

Hasil:

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

Jalur Duplikat

Jika dokumen JSON Anda berisi jalur duplikat pada tingkat bersarang yang sama, OPENJSON() dapat mengembalikan semuanya.

Ini berbeda dengan JSON_VALUE() dan JSON_QUERY() , keduanya hanya mengembalikan nilai pertama yang cocok dengan jalurnya.

Berikut ini contoh penggunaan OPENJSON() untuk mengembalikan jalur duplikat.

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

Hasil:

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

Sub-Objek Bersarang

Saat mendefinisikan skema Anda sendiri, Anda dapat menggunakan AS JSON opsi untuk mengembalikan seluruh sub-objek sebagai dokumen JSON-nya sendiri.

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

Hasil:

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

Jika kami tidak menggunakan AS JSON opsi, kami akan menerima kesalahan atau NULL, tergantung pada apakah kami telah menentukan lax atau strict modus.

Ini dia di setiap mode saat menghilangkan AS JSON pilihan.

Mode longgar

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

Hasil:

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

Mode ketat

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

Hasil:

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

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Permintaan rekursif SQL Server

  2. Bagaimana cara menentukan nomor port dalam string koneksi SQL Server?

  3. Cara Mengatur Spotlight Cloud dan Memecahkan Masalah SQL Server secara Efisien

  4. Apakah UNION ALL menjamin urutan set hasil?

  5. Bagaimana Mengidentifikasi duplikasi kunci utama dari kode kesalahan SQL Server 2008?