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 atauNULL
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.