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

Pengenalan OPENJSON dengan Contoh (SQL Server)

SQL Server memiliki fungsi bernilai tabel yang disebut OPENJSON() yang membuat tampilan relasional data JSON.

Saat Anda memanggilnya, Anda meneruskan dokumen JSON sebagai argumen, dan OPENJSON() kemudian menguraikannya dan mengembalikan objek dan properti dokumen JSON dalam format tabel – sebagai baris dan kolom.

Contoh

Berikut adalah contoh sederhana untuk didemonstrasikan.

SELECT * FROM OPENJSON('["Cat","Dog","Bird"]');

Hasil:

+-------+---------+--------+
| key   | value   | type   |
|-------+---------+--------|
| 0     | Cat     | 1      |
| 1     | Dog     | 1      |
| 2     | Bird    | 1      |
+-------+---------+--------+

Secara default, OPENJSON() mengembalikan tabel dengan tiga kolom; kunci , nilai , dan ketik .

Anda juga memiliki opsi untuk menentukan skema Anda sendiri (yang berarti Anda dapat menentukan kolom Anda sendiri). Dalam contoh sederhana saya, saya menggunakan skema default, sehingga tiga kolom default dikembalikan.

Kolom-kolom ini didefinisikan sebagai berikut:

Kolom Deskripsi
kunci Berisi nama properti yang ditentukan atau indeks elemen dalam larik yang ditentukan. Ini adalah nvarchar(4000) nilai, dan kolom memiliki susunan BIN2.
nilai Berisi nilai properti. Ini adalah nvarchar(maks) nilai, dan kolom mewarisi susunannya dari JSON yang disediakan.
ketik Berisi jenis nilai JSON. Ini direpresentasikan sebagai int nilai (dari 0 ke 5 ). Kolom ini hanya ditampilkan saat Anda menggunakan skema default.

Tipe Default

Di dunia JSON, ada enam tipe data. Ini adalah string , angka , benar/salah (boolean), null , objek , dan larik .

Saat Anda mengurai beberapa JSON melalui OPENJSON() menggunakan skema default, OPENJSON() mencari tahu apa jenis JSON itu, lalu mengisi jenis kolom dengan int nilai yang mewakili tipe tersebut.

int nilai karena itu dapat berkisar dari 0 ke 5 . Setiap int value mewakili tipe JSON seperti yang dijelaskan dalam tabel berikut.

Nilai di kolom “jenis” Tipe data JSON
0 nol
1 string
2 angka
3 benar/salah
4 susunan
5 objek

Contoh berikut mengembalikan keenam jenis JSON ini.

SELECT * FROM OPENJSON('{"name" : null}');
SELECT * FROM OPENJSON('["Cat","Dog","Bird"]');
SELECT * FROM OPENJSON('[1,2,3]');
SELECT * FROM OPENJSON('[true,false]');
SELECT * FROM OPENJSON('{"cats":[{ "id":1, "name":"Fluffy"},{ "id":2, "name":"Scratch"}]}');
SELECT * FROM OPENJSON('[{"A":1,"B":0,"C":1}]');

Hasil:

+-------+---------+--------+
| key   | value   | type   |
|-------+---------+--------|
| name  | NULL    | 0      |
+-------+---------+--------+
(1 row affected)
+-------+---------+--------+
| key   | value   | type   |
|-------+---------+--------|
| 0     | Cat     | 1      |
| 1     | Dog     | 1      |
| 2     | Bird    | 1      |
+-------+---------+--------+
(3 rows affected)
+-------+---------+--------+
| key   | value   | type   |
|-------+---------+--------|
| 0     | 1       | 2      |
| 1     | 2       | 2      |
| 2     | 3       | 2      |
+-------+---------+--------+
(3 rows affected)
+-------+---------+--------+
| key   | value   | type   |
|-------+---------+--------|
| 0     | true    | 3      |
| 1     | false   | 3      |
+-------+---------+--------+
(2 rows affected)
+-------+----------------------------------------------------------+--------+
| key   | value                                                    | type   |
|-------+----------------------------------------------------------+--------|
| cats  | [{ "id":1, "name":"Fluffy"},{ "id":2, "name":"Scratch"}] | 4      |
+-------+----------------------------------------------------------+--------+
(1 row affected)
+-------+---------------------+--------+
| key   | value               | type   |
|-------+---------------------+--------|
| 0     | {"A":1,"B":0,"C":1} | 5      |
+-------+---------------------+--------+
(1 row affected)

Kembalikan JSON Bersarang

Anda dapat mengembalikan objek atau larik bersarang dengan menetapkan jalurnya sebagai argumen kedua opsional.

Dengan kata lain, Anda tidak perlu mengurai seluruh dokumen JSON – Anda dapat memilih untuk mengurai bagian yang Anda minati saja.

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" : [
            { "name" : "Fetch", "sex" : "Male" },
            { "name" : "Fluffy", "sex" : "Male" },
            { "name" : "Wag", "sex" : "Female" }
        ]
    }
}';
SELECT * FROM OPENJSON(@json, '$.pets.cats');

Hasil:

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

Dalam hal ini, saya menentukan jalur $.pets.cats , yang hanya menghasilkan nilai kucing dikembalikan. Nilai kucing adalah array, jadi seluruh array dikembalikan.

Untuk mengembalikan hanya satu cat (yaitu satu elemen larik), kita dapat menggunakan sintaks kurung siku untuk mengembalikan nilai larik (seperti ini $.pets.cats[1] ).

Berikut contoh yang sama yang dimodifikasi untuk mengembalikan hanya satu elemen array:

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" : [
            { "name" : "Fetch", "sex" : "Male" },
            { "name" : "Fluffy", "sex" : "Male" },
            { "name" : "Wag", "sex" : "Female" }
        ]
    }
}';
SELECT * FROM OPENJSON(@json, '$.pets.cats[1]');

Hasil:

+-------+-----------+--------+
| key   | value     | type   |
|-------+-----------+--------|
| id    | 2         | 2      |
| name  | Long Tail | 1      |
| sex   | Female    | 1      |
+-------+-----------+--------+

Indeks array JSON berbasis nol, jadi contoh ini mengembalikan nilai array kedua (karena saya menetapkan $.pets.cats[1] ).

Jika saya telah menentukan $.pets.cats[0] , nilai pertama akan dikembalikan (yaitu kucing bernama “Fluffy”).

Tentukan Skema

Seperti yang disebutkan, Anda dapat menentukan skema Anda sendiri (yaitu menentukan kolom dan tipe Anda sendiri).

Berikut ini contoh melakukannya.

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" : [
            { "name" : "Fetch", "sex" : "Male" },
            { "name" : "Fluffy", "sex" : "Male" },
            { "name" : "Wag", "sex" : "Female" }
        ]
    }
}';

SELECT * FROM OPENJSON(@json, '$.pets.cats')
WITH  (
        [Cat Id]    int             '$.id',  
        [Cat Name]  varchar(60)     '$.name', 
        [Sex]       varchar(6)      '$.sex', 
        [Cats]      nvarchar(max)   '$' AS JSON   
    );

Hasil:

+----------+------------+--------+------------------------------------------------------+
| Cat Id   | Cat Name   | Sex    | Cats                                                 |
|----------+------------+--------+------------------------------------------------------|
| 1        | Fluffy     | Female | { "id" : 1, "name" : "Fluffy", "sex" : "Female" }    |
| 2        | Long Tail  | Female | { "id" : 2, "name" : "Long Tail", "sex" : "Female" } |
| 3        | Scratch    | Male   | { "id" : 3, "name" : "Scratch", "sex" : "Male" }     |
+----------+------------+--------+------------------------------------------------------+

Kita dapat melihat bahwa nama kolom mencerminkan yang saya tentukan di WITH ayat. Dalam klausa itu, saya memetakan setiap kunci JSON ke nama kolom pilihan saya sendiri. Saya juga menentukan tipe data SQL Server yang saya inginkan untuk setiap kolom.

Saya juga menggunakan AS JSON pada kolom terakhir untuk mengembalikan kolom itu sebagai fragmen JSON. Saat Anda menggunakan AS JSON, tipe datanya harus nvarchar(max) .

Verifikasi Jenis Data

Kita dapat menggunakan kueri berikut untuk memverifikasi tipe data setiap kolom.

Kueri ini menggunakan sys.dm_exec_describe_first_result_set tampilan manajemen dinamis sistem, yang mengembalikan metadata tentang kumpulan hasil pertama dari kueri.

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" : [
            { "name" : "Fetch", "sex" : "Male" },
            { "name" : "Fluffy", "sex" : "Male" },
            { "name" : "Wag", "sex" : "Female" }
        ]
    }
}';

SELECT 
    name,
    system_type_name
FROM sys.dm_exec_describe_first_result_set(
    'SELECT * FROM OPENJSON(@json, ''$.pets.cats'') WITH  (
        [Cat Id]    int             ''$.id'',  
        [Cat Name]  varchar(60)     ''$.name'', 
        [Sex]       varchar(6)      ''$.sex'', 
        [Cats]      nvarchar(max)   ''$'' AS JSON 
    )',
    null,
    0
);

Hasil:

+----------+--------------------+
| name     | system_type_name   |
|----------+--------------------|
| Cat Id   | int                |
| Cat Name | varchar(60)        |
| Sex      | varchar(6)         |
| Cats     | nvarchar(max)      |
+----------+--------------------+

Kita dapat melihat bahwa mereka sangat cocok dengan skema saya.

Perhatikan bahwa kunci , nilai , dan ketik kolom tidak tersedia saat Anda menentukan skema Anda sendiri. Kolom tersebut hanya tersedia saat menggunakan skema default.

Memasukkan JSON yang Diurai ke dalam Tabel

Sekarang Anda mungkin berpikir bahwa kami dapat dengan mudah memasukkan JSON yang telah diurai ke dalam tabel database.

Dan Anda benar.

Kami telah menyiapkannya dengan kolom dan baris, dan kami bahkan telah menamai kolom dan memberinya tipe data.

Sekarang saatnya untuk memasukkannya ke dalam tabel.

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" : [
            { "name" : "Fetch", "sex" : "Male" },
            { "name" : "Fluffy", "sex" : "Male" },
            { "name" : "Wag", "sex" : "Female" }
        ]
    }
}';

SELECT * INTO JsonCats
FROM OPENJSON(@json, '$.pets.cats')
WITH  (
        [Cat Id]    int             '$.id',  
        [Cat Name]  varchar(60)     '$.name', 
        [Sex]       varchar(6)      '$.sex', 
        [Cats]      nvarchar(max)   '$' AS JSON   
    );

Yang saya lakukan hanyalah menambahkan INTO JsonCats untuk permintaan saya, untuk membuat tabel bernama JsonCats dan masukkan hasil kueri ke dalamnya.

Sekarang mari kita pilih isi tabel itu.

SELECT * FROM JsonCats;

Hasil:

+----------+------------+--------+------------------------------------------------------+
| Cat Id   | Cat Name   | Sex    | Cats                                                 |
|----------+------------+--------+------------------------------------------------------|
| 1        | Fluffy     | Female | { "id" : 1, "name" : "Fluffy", "sex" : "Female" }    |
| 2        | Long Tail  | Female | { "id" : 2, "name" : "Long Tail", "sex" : "Female" } |
| 3        | Scratch    | Male   | { "id" : 3, "name" : "Scratch", "sex" : "Male" }     |
+----------+------------+--------+------------------------------------------------------+

Isinya persis seperti yang kita lihat di contoh sebelumnya.

Dan untuk memastikannya, sekarang kita dapat menggunakan sys.column tampilan katalog sistem memeriksa nama dan jenis kolom tabel.

SELECT
    name AS [Column],
    TYPE_NAME(system_type_id) AS [Type],
    max_length
FROM sys.columns 
WHERE OBJECT_ID('JsonCats') = object_id;

Hasil:

+----------+----------+--------------+
| Column   | Type     | max_length   |
|----------+----------+--------------|
| Cat Id   | int      | 4            |
| Cat Name | varchar  | 60           |
| Sex      | varchar  | 6            |
| Cats     | nvarchar | -1           |
+----------+----------+--------------+

Sekali lagi, persis seperti yang kami tentukan.

Perhatikan bahwa sys.columns selalu mengembalikan max_length dari -1 ketika tipe data kolom adalah varchar(max) , nvarchar(maks) , varbinary(maks) , atau xml . Kami menentukan nvarchar(max) jadi nilai -1 persis seperti yang diharapkan.

Mode Jalur:Lax vs Ketat

Jalur yang disediakan dalam argumen kedua atau di WITH klausa dapat (opsional) dimulai dengan lax atau strict kata kunci.

  • Dalam lax mode, OPENJSON() tidak menimbulkan kesalahan jika objek atau nilai pada jalur yang ditentukan tidak dapat ditemukan. Jika jalur tidak dapat ditemukan, OPENJSON() mengembalikan kumpulan hasil kosong atau NULL nilai.
  • Dalam strict mode, OPENJSON() mengembalikan kesalahan jika jalur tidak dapat ditemukan.

Nilai defaultnya adalah lax , jadi jika Anda tidak menentukan mode jalur, lax mode akan digunakan.

Berikut adalah beberapa contoh untuk mendemonstrasikan apa yang terjadi dengan setiap mode ketika jalur tidak dapat ditemukan.

Argumen Kedua

Dalam dua contoh berikutnya, saya memberikan jalur yang tidak ada dalam argumen kedua saat memanggil OPENJSON() . Contoh pertama menunjukkan apa yang terjadi saat menggunakan mode longgar, contoh kedua menunjukkan apa yang terjadi saat menggunakan mode ketat.

Mode Lemah

Inilah yang terjadi di lax mode ketika jalur tidak dapat ditemukan.

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" : [
            { "name" : "Fetch", "sex" : "Male" },
            { "name" : "Fluffy", "sex" : "Male" },
            { "name" : "Wag", "sex" : "Female" }
        ]
    }
}';
SELECT * FROM OPENJSON(@json, 'lax $.pets.cows');

Hasil:

(0 rows affected)

Tidak ada kesalahan. Hanya nol hasil yang dikembalikan.

Mode Ketat

Sekarang di sini dalam strict mode.

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" : [
            { "name" : "Fetch", "sex" : "Male" },
            { "name" : "Fluffy", "sex" : "Male" },
            { "name" : "Wag", "sex" : "Female" }
        ]
    }
}'
SELECT * FROM OPENJSON(@json, 'strict $.pets.cows');

Hasil:

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

Seperti yang diharapkan, mode ketat menghasilkan kesalahan.

Dalam Klausa WITH

Dalam dua contoh berikutnya, kita kembali menguji mode lax vs mode ketat, kecuali kali ini kita menentukannya di WITH klausa saat mendefinisikan skema.

Mode Lax

Inilah yang terjadi di lax modus.

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" : [
            { "name" : "Fetch", "sex" : "Male" },
            { "name" : "Fluffy", "sex" : "Male" },
            { "name" : "Wag", "sex" : "Female" }
        ]
    }
}';

SELECT *
FROM OPENJSON(@json, '$.pets.cats')
WITH  (
        [Cat Id]    int             '$.id',  
        [Cat Name]  varchar(60)     '$.name', 
        [Born]      date            'lax $.born', 
        [Cats]      nvarchar(max)   '$' AS JSON   
    );

Hasil:

+----------+------------+--------+------------------------------------------------------+
| Cat Id   | Cat Name   | Born   | Cats                                                 |
|----------+------------+--------+------------------------------------------------------|
| 1        | Fluffy     | NULL   | { "id" : 1, "name" : "Fluffy", "sex" : "Female" }    |
| 2        | Long Tail  | NULL   | { "id" : 2, "name" : "Long Tail", "sex" : "Female" } |
| 3        | Scratch    | NULL   | { "id" : 3, "name" : "Scratch", "sex" : "Male" }     |
+----------+------------+--------+------------------------------------------------------+

Dalam hal ini saya menggunakan 'lax $.born' karena saya mencoba mereferensikan kunci yang disebut born , tetapi kunci seperti itu tidak ada di JSON.

Kali ini kolom yang tidak dapat ditemukan menghasilkan NULL nilai.

Mode Ketat

Sekarang di sini dalam strict modus.

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" : [
            { "name" : "Fetch", "sex" : "Male" },
            { "name" : "Fluffy", "sex" : "Male" },
            { "name" : "Wag", "sex" : "Female" }
        ]
    }
}';

SELECT *
FROM OPENJSON(@json, '$.pets.cats')
WITH  (
        [Cat Id]    int             '$.id',  
        [Cat Name]  varchar(60)     '$.name', 
        [Born]      date            'strict $.born', 
        [Cats]      nvarchar(max)   '$' AS JSON   
    );

Hasil:

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

Kali ini saya menggunakan 'strict $.born' .

Seperti yang diharapkan, mode ketat menghasilkan kesalahan.

Tingkat Kompatibilitas

OPENJSON() fungsi hanya tersedia di bawah tingkat kompatibilitas 130 atau lebih tinggi.

Jika tingkat kompatibilitas database Anda lebih rendah dari 130, SQL Server tidak akan dapat menemukan dan menjalankan OPENJSON() , dan Anda akan mendapatkan pesan kesalahan.

Anda dapat memeriksa tingkat kompatibilitas database Anda melalui sys.databases tampilan katalog.

Anda dapat mengubah tingkat kompatibilitasnya seperti ini:

ALTER DATABASE DatabaseName 
SET COMPATIBILITY_LEVEL = 150;

Baru menggunakan JSON?

Jika Anda tidak begitu akrab dengan JSON, lihat tutorial JSON saya di Quackit.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Alih-alih pemicu di SQL Server kehilangan SCOPE_IDENTITY?

  2. Pemicu Masuk di SQL Server

  3. Bagaimana cara memeriksa apakah ada Kendala di server Sql?

  4. Cara Menginstal sqlcmd &bcp di Ubuntu

  5. Dapatkan hari pertama dalam seminggu di SQL Server