Lindorm SQL menyediakan fungsi JSON untuk membuat, mengekstraksi, memeriksa keberadaan, dan memperbarui data JSON yang disimpan dalam kolom JSON. Referensi ini menjelaskan sintaksis, parameter, perilaku, serta contoh setiap fungsi.
Ikhtisar fungsi
| Kategori | Fungsi | Deskripsi |
|---|---|---|
| Constructor | json_object | Membuat objek JSON. |
| Constructor | json_array | Membuat array JSON. |
| Extraction | json_extract | Mengekstraksi nilai pada path yang ditentukan. |
| Extraction | json_extract_string | Mengekstraksi nilai pada path yang ditentukan dan mengembalikannya sebagai VARCHAR. |
| Extraction | json_extract_long | Mengekstraksi nilai pada path yang ditentukan dan mengembalikannya sebagai LONG. |
| Extraction | json_extract_double | Mengekstraksi nilai pada path yang ditentukan dan mengembalikannya sebagai Double. |
| Containment check | json_contains | Mengembalikan 1 jika dokumen JSON berisi semua nilai yang ditentukan. |
| Containment check | json_contains_any | Mengembalikan 1 jika dokumen JSON berisi salah satu dari nilai yang ditentukan. |
| Update | json_set | Menyisipkan atau memperbarui nilai pada suatu path. Setara dengan json_insert + json_replace. |
| Update | json_insert | Menyisipkan nilai pada suatu path hanya jika path tersebut belum ada. |
| Update | json_replace | Memperbarui nilai pada suatu path hanya jika path tersebut sudah ada. |
| Update | json_remove | Menghapus nilai pada path yang ditentukan. |
| Update | json_upsert | Sama seperti json_set, tetapi membuat objek baru jika kolom JSON bernilai NULL. |
Ekspresi path JSON
Semua fungsi ekstraksi, pemeriksaan keberadaan, dan pembaruan menerima ekspresi path JSON untuk mengidentifikasi lokasi dalam dokumen JSON.
| Simbol | Deskripsi | Contoh |
|---|---|---|
$ | Akar dokumen | $ |
.key | Akses anggota objek | $.name |
[n] | Akses elemen array (indeks dimulai dari 0) | $.skills[0] |
.nested.key | Akses bidang bersarang | $.address.city |
Contoh dokumen JSON:
{
"name": "Alice",
"age": 25,
"address": { "city": "Beijing" },
"skills": ["Java", "Python"]
}| Path | Hasil |
|---|---|
$.name | "Alice" |
$.age | 25 |
$.address.city | "Beijing" |
$.skills[0] | "Java" |
$.skills | ["Java", "Python"] |
Fungsi constructor
json_object
Membuat objek JSON dari pasangan kunci-nilai.
Sintaksis
json_object(key1, value1, key2, value2, ...)Parameter
| Parameter | Deskripsi |
|---|---|
key | Nama kunci. Harus berupa string. |
value | Nilainya. Dapat berupa tipe apa pun. |
Contoh
Buat objek sederhana:
SELECT json_object('name', 'Alice', 'age', 25);
-- Result: {"name": "Alice", "age": 25}Gunakan dalam pernyataan UPSERT:
UPSERT INTO users (id, data) VALUES (1, json_object('name', 'Charlie', 'city', 'Beijing'));json_array
Membuat array JSON dari daftar nilai.
Sintaksis
json_array(value1, value2, value3, ...)Parameter
| Parameter | Deskripsi |
|---|---|
value | Nilainya. Dapat berupa skalar, objek, atau array. |
Contoh
Buat array sederhana:
SELECT json_array('apple', 'banana', 'orange');
-- Result: ["apple", "banana", "orange"]Gunakan dalam pernyataan UPSERT:
UPSERT INTO products (id, tags) VALUES (1, json_array('electronics', 'mobile', 'smartphone'));Fungsi ekstraksi
Semua fungsi ekstraksi menerima kolom JSON dan ekspresi path. Tiga fungsi ekstraksi bertipe (json_extract_string, json_extract_long, json_extract_double) bersifat strongly typed — nilai pada path harus sesuai dengan tipe yang diharapkan oleh fungsi. Jika tipe tidak cocok, fungsi mengembalikan NULL atau melemparkan error. Definisikan tipe data sebelum memasukkan data JSON untuk menghindari perilaku tak terduga akibat pencampuran tipe.
json_extract
Mengekstraksi nilai dari dokumen JSON pada path yang ditentukan dan mengembalikannya dalam tipe JSON aslinya.
Sintaksis
json_extract(json_column, 'path')Parameter
| Parameter | Deskripsi |
|---|---|
json_column | Kolom atau ekspresi bertipe JSON. |
path | Ekspresi path JSON, seperti $.field, $.array[0], atau $.nested.field. |
Contoh
Ekstraksi bidang tingkat atas:
SELECT json_extract('{"name": "Alice", "age": 25}', '$.name');
-- Result: "Alice"Ekstraksi bidang bersarang:
SELECT json_extract('{"user": {"name": "Bob", "age": 30}}', '$.user.name');
-- Result: "Bob"Ekstraksi elemen array:
SELECT json_extract('{"skills": ["Java", "Python"]}', '$.skills[0]');
-- Result: "Java"Ekstraksi seluruh array:
SELECT json_extract('{"skills": ["Java", "Python"]}', '$.skills');
-- Result: ["Java", "Python"]Gunakan dalam klausa WHERE dengan perbandingan numerik:
SELECT * FROM tb WHERE json_extract(c2, '$.k3.k4') > 5;Gunakan dalam klausa WHERE dengan perbandingan string (gunakan json_extract_string untuk type safety):
SELECT * FROM tb WHERE json_extract_string(c2, '$.k2') = '1';json_extract_string
Mengekstraksi nilai pada path yang ditentukan dan mengembalikannya sebagai VARCHAR. Jika nilai pada path bukan string, fungsi mengembalikan NULL.
Contoh
Nilai pada $.name adalah string, sehingga mengembalikan VARCHAR:
SELECT json_extract_string('{"name": "Alice"}', '$.name');
-- Result: Alice (VARCHAR)Nilai pada $.number adalah angka, bukan string, sehingga fungsi mengembalikan NULL:
SELECT json_extract_string('{"number": 30}', '$.number');
-- Result: NULLjson_extract_long
Mengekstraksi nilai pada path yang ditentukan dan mengembalikannya sebagai LONG. Jika nilai pada path bukan angka, Java Database Connectivity (JDBC) melemparkan error.
Contoh
Nilainya adalah integer, sehingga mengembalikan LONG:
SELECT json_extract_long('{"id": 123456789}', '$.id');
-- Result: 123456789 (LONG)Nilainya adalah bilangan titik mengambang — JDBC melemparkan error:
SELECT json_extract_long('{"id": 123456.789}', '$.id');
-- Throws an errorNilainya adalah string numerik — JDBC melemparkan error:
SELECT json_extract_long('{"id": "123456.789"}', '$.id');
-- Throws an errorjson_extract_double
Mengekstraksi nilai pada path yang ditentukan dan mengembalikannya sebagai Double. Jika nilai pada path bukan bilangan titik mengambang, JDBC melemparkan error.
Contoh
Nilainya adalah bilangan titik mengambang, sehingga mengembalikan Double:
SELECT json_extract_double('{"id": 12345.56}', '$.id');
-- Result: 12345.56 (Double)Nilainya adalah integer — fungsi mengembalikannya sebagai Double:
SELECT json_extract_double('{"id": 12345}', '$.id');
-- Result: 12345.0 (Double)Nilainya adalah string numerik — JDBC melemparkan error:
SELECT json_extract_double('{"id": "123456.789"}', '$.id');
-- Throws an errorFungsi Pemeriksaan Penampungan
json_contains
Mengembalikan 1 jika target_json berisi semua elemen dalam candidate_json, dan 0 jika tidak. Secara opsional, tentukan path untuk memeriksa keberadaan pada lokasi tertentu dalam dokumen.
Mengembalikan NULL jika path yang ditentukan tidak ada atau jika ada parameter yang bernilai NULL.
Sintaksis
json_contains(target_json, candidate_json[, path])Parameter
| Parameter | Wajib | Deskripsi |
|---|---|---|
target_json | Ya | Dokumen JSON yang akan dicari. |
candidate_json | Ya | Dokumen JSON yang akan diperiksa. Harus berupa string JSON yang valid. |
path | Tidak | Path untuk diperiksa dalam target_json. Default-nya adalah $ (akar). |
Cara memformat `candidate_json`
candidate_json harus berupa string JSON yang valid yang merepresentasikan elemen yang akan diperiksa:
| Apa yang diperiksa | candidate_json nilai |
|---|---|
Angka 10 | '10' |
String "10" | '"10"' |
| Daftar angka | '[1,2,3]' |
| Daftar string | '["10","abc","key"]' |
Klasifikasi tipe JSON
Skalar: String, Angka (Integer/Double), Boolean, Null
Tipe kompleks: Array, Objek
Aturan Pembatasan
Skalar hanya dapat berisi skalar lain, bukan array.
Array dapat berisi elemen (skalar) atau subset array.
Contoh
Persiapkan tabel contoh yang digunakan dalam kueri berikut:
CREATE TABLE test_table (id INT, c1 VARCHAR, data JSON, PRIMARY KEY(id));
UPSERT INTO test_table (id, data) VALUES (1, NULL);
UPSERT INTO test_table (id, data) VALUES (2, '{"skills": ["Java", "Python"]}');
UPSERT INTO test_table (id, data) VALUES (3, '{"skills": ["Go", "C"]}');
UPSERT INTO test_table (id, data) VALUES (4, '{"technical_skills": ["Java", "Go", "Rust"]}');
UPSERT INTO test_table (id, data) VALUES (5, '["Java","C++", "JavaScript"]');
UPSERT INTO test_table (id, data) VALUES (6, '{"skills": "Java"}');
UPSERT INTO test_table (id, data) VALUES (7, '["Java", "C#"]');
UPSERT INTO test_table (id, data) VALUES (8, '{"skills": ["Go", "Rust"]}');Bentuk dua parameter memeriksa seluruh dokumen (path akar $). Ini menemukan baris di mana dokumen tingkat atas adalah array yang berisi "Java":
SELECT id, data FROM test_table WHERE json_contains(data, '["Java"]') AND id > 0 AND id < 10;+------+------------------------------+
| id | data |
+------+------------------------------+
| 5 | ["Java","C++", "JavaScript"] |
| 7 | ["Java", "C#"] |
+------+------------------------------+Bentuk tiga parameter memeriksa path tertentu. Ini menemukan baris di mana $.skills adalah array yang berisi "Java":
SELECT id, data FROM test_table WHERE json_contains(data, '["Java"]', '$.skills') AND id > 0 AND id < 10;+------+--------------------------------+
| id | data |
+------+--------------------------------+
| 2 | {"skills": ["Java", "Python"]} |
+------+--------------------------------+json_contains mengharuskan semua elemen candidate_json hadir. Kueri ini tidak menemukan baris karena tidak ada array $.skills yang berisi kedua "Java" dan "Go":
SELECT id, data FROM test_table WHERE json_contains(data, '["Java","Go"]', '$.skills') AND id > 0 AND id < 10;
-- Empty setMenggunakan skalar "Java" sebagai kandidat cocok dengan array yang berisi "Java" dan skalar yang sama dengan "Java":
SELECT id, data FROM test_table WHERE json_contains(data, '"Java"', '$.skills') AND id > 0 AND id < 10;+------+--------------------------------+
| id | data |
+------+--------------------------------+
| 2 | {"skills": ["Java", "Python"]} |
| 6 | {"skills": "Java"} |
+------+--------------------------------+Periksa apakah objek berisi pasangan kunci-nilai:
SELECT json_contains('{"a": 1, "b": 2}', '{"a": 1}');
-- Result: 1Periksa apakah path tertentu berisi nilai tertentu:
SELECT json_contains('{"a": 1, "b": 2}', '1', '$.a');
-- Result: 1
SELECT json_contains('{"a": 1, "b": 2}', '1', '$.b');
-- Result: 0json_contains_any
Mengembalikan 1 jika target_json berisi setidaknya satu elemen dari candidate_json. Menggunakan sintaksis dan parameter yang sama seperti json_contains.
Contoh
Tanpa path, memeriksa dokumen akar. Dokumen tingkat atas adalah objek, bukan array yang secara langsung berisi "Java" atau "Go":
SELECT json_contains_any('{"skills": ["Java", "Python"]}', '["Java", "Go"]');
-- Result: 0Dengan path, memeriksa $.skills. Array pada $.skills berisi "Java", yang cocok dengan salah satu elemen kandidat:
SELECT json_contains_any('{"skills": ["Java", "Python"]}', '["Java", "Go"]', '$.skills');
-- Result: 1Bentuk dua parameter menemukan baris di mana dokumen tingkat atas adalah array dengan elemen apa pun dari ["Java", "Go"]:
SELECT id, data FROM test_table WHERE json_contains_any(data, '["Java", "Go"]') LIMIT 10;+------+------------------------------+
| id | data |
+------+------------------------------+
| 5 | ["Java","C++", "JavaScript"] |
| 7 | ["Java", "C#"] |
+------+------------------------------+Bentuk tiga parameter menemukan baris di mana $.skills berisi elemen apa pun dari daftar kandidat:
SELECT id, data FROM test_table WHERE json_contains_any(data, '["Java", "Go", "Rust"]', '$.skills') LIMIT 10;+------+--------------------------------+
| id | data |
+------+--------------------------------+
| 2 | {"skills": ["Java", "Python"]} |
| 3 | {"skills": ["Go", "C"]} |
| 6 | {"skills": "Java"} |
| 8 | {"skills": ["Go", "Rust"]} |
+------+--------------------------------+Periksa apakah path tertentu berisi nilai apa pun dari array kandidat:
SELECT json_contains_any('{"departments": ["Engineering", "Sales"]}', '["Marketing", "Engineering"]', '$.departments');
-- Result: 1Memahami keberadaan skalar vs. array pada path
Pertimbangkan json_contains_any(data, '["Java"]', '$.technical_skills'). Perilakunya bergantung pada tipe JSON pada $.technical_skills:
Jika nilainya adalah
{"technical_skills": "Java"}(string skalar), fungsi mengembalikanfalse. Subset dari skalar tidak bisa berupa daftar.Jika nilainya adalah
{"technical_skills": ["Java"]}atau{"technical_skills": ["Java", "Go"]}(array), fungsi mengembalikantrue.
Pertimbangkan json_contains_any(data, '"Java"', '$.technical_skills'). Menggunakan kandidat skalar:
Jika nilainya adalah
{"technical_skills": "Java"}(string skalar yang sama dengan"Java"), fungsi mengembalikantrue.Jika nilainya adalah
{"technical_skills": ["Java"]}atau{"technical_skills": ["Java", "Go"]}(array yang berisi"Java"), fungsi mengembalikantrue.
Fungsi pembaruan
json_set
Menyisipkan atau memperbarui nilai pada path yang ditentukan. Jika path sudah ada, nilai diperbarui. Jika path belum ada, nilai disisipkan. Jika kolom JSON bernilai NULL, hasilnya adalah NULL — objek baru tidak dibuat.
Setara dengan json_insert + json_replace.
Sintaksis
json_set(json_column, 'path', new_value)Contoh
Perbarui bidang yang sudah ada:
UPSERT INTO test_table (id, data) VALUES (3, '{"name": "Charlie", "age": 30}');
UPDATE test_table SET data = json_set(data, '$.age', 31) WHERE id = 3;
-- Result: {"name": "Charlie", "age": 31}Sisipkan bidang baru:
UPDATE test_table SET data = json_set(data, '$.department', 'Engineering') WHERE id = 3;
-- Result: {"name": "Charlie", "age": 31, "department": "Engineering"}Jika kolom JSON bernilai NULL, hasilnya tetap NULL:
UPSERT INTO test_table (id, c1) VALUES (4, 'test');
UPDATE test_table SET data = json_set(data, '$.name', 'David') WHERE id = 4;
-- Result: NULLjson_insert
Menyisipkan nilai pada path yang ditentukan hanya jika path tersebut belum ada. Jika path sudah ada, fungsi tidak melakukan apa-apa.
json_insert tidak menimpa nilai yang sudah ada. Upaya menyisipkan ke bidang yang sudah ada diam-diam tidak berpengaruh — nilai asli dipertahankan.Sintaksis
json_insert(json_column, 'path', new_value)Contoh
Sisipkan bidang baru:
UPSERT INTO test_table (id, data) VALUES (5, '{"name": "Eve"}');
UPDATE test_table SET data = json_insert(data, '$.age', 28) WHERE id = 5;
-- Result: {"name": "Eve", "age": 28}Mencoba menyisipkan ke bidang yang sudah ada tidak berpengaruh — bidang name tetap tidak berubah:
UPDATE test_table SET data = json_insert(data, '$.name', 'New Name') WHERE id = 5;
-- Result: {"name": "Eve", "age": 28}json_replace
Memperbarui nilai pada path yang ditentukan hanya jika path tersebut sudah ada. Jika path belum ada, fungsi tidak melakukan apa-apa.
Sintaksis
json_replace(json_column, 'path', new_value)Contoh
Perbarui bidang yang sudah ada:
UPSERT INTO test_table (id, data) VALUES (6, '{"name": "Frank", "age": 35}');
UPDATE test_table SET data = json_replace(data, '$.age', 36) WHERE id = 6;
-- Result: {"name": "Frank", "age": 36}Mencoba memperbarui bidang yang tidak ada tidak berpengaruh — bidang city tidak ditambahkan:
UPDATE test_table SET data = json_replace(data, '$.city', 'Shanghai') WHERE id = 6;
-- Result: {"name": "Frank", "age": 36}json_remove
Menghapus nilai pada path yang ditentukan dan mengembalikan dokumen yang telah dimodifikasi. Jika path tidak ada, operasi berhasil tanpa error.
Sintaksis
json_remove(json_column, 'path')Contoh
Hapus bidang:
UPSERT INTO test_table (id, data) VALUES (7, '{"name": "Grace", "temp_field": "to_remove"}');
UPDATE test_table SET data = json_remove(data, '$.temp_field') WHERE id = 7;
-- Result: {"name": "Grace"}Menghapus bidang yang tidak ada tidak berpengaruh dan mengembalikan dokumen tanpa perubahan:
UPDATE test_table SET data = json_remove(data, '$.nonexistent') WHERE id = 7;
-- Result: {"name": "Grace"}json_upsert
Menyisipkan atau memperbarui nilai pada path yang ditentukan. Berperilaku seperti json_set, dengan satu perbedaan utama: jika kolom JSON bernilai NULL, json_upsert membuat objek JSON baru alih-alih mengembalikan NULL.
Sintaksis
json_upsert(json_column, 'path', new_value)Contoh
Ketika kolom JSON bernilai NULL, json_upsert membuat objek baru:
CREATE TABLE test_table (id INT, c1 VARCHAR, data JSON, PRIMARY KEY(id));
UPSERT INTO test_table (id, c1) VALUES (1, 'test');
UPDATE test_table SET data = json_upsert(data, '$.name', 'Alice') WHERE id = 1;
-- Result: {"name": "Alice"}Perbarui bidang yang sudah ada:
UPSERT INTO test_table (id, data) VALUES (2, '{"name": "Bob", "age": 25}');
UPDATE test_table SET data = json_upsert(data, '$.age', 26) WHERE id = 2;
-- Result: {"name": "Bob", "age": 26}Sisipkan bidang baru:
UPDATE test_table SET data = json_upsert(data, '$.city', 'Beijing') WHERE id = 2;
-- Result: {"name": "Bob", "age": 26, "city": "Beijing"}Perbandingan fungsi
Fungsi pemeriksaan keterkandungan
| Fungsi | Perilaku |
|---|---|
json_contains | Setiap elemen dalam candidate_json harus ada dalam target_json. (candidate_json adalah subset dari target_json.) |
json_contains_any | Setidaknya satu elemen dalam candidate_json harus ada dalam target_json. |
Fungsi pembaruan
| Fungsi | Kolom NULL | Path ada | Path tidak ada | Gunakan saat |
|---|---|---|---|---|
json_set | Tetap NULL | Pembaruan | Menyisipkan | Kolom diketahui tidak NULL. Sesuai dengan semantik MySQL. |
json_upsert | Membuat {path: value} | Memperbarui | Menyisipkan | Pembaruan tujuan umum, termasuk saat kolom mungkin NULL. |
json_insert | Tetap NULL | Tidak ada aksi | Penyisipan | Menambahkan bidang baru tanpa memodifikasi nilai yang sudah ada. |
json_replace | Tetap NULL | Memperbarui | Tidak ada aksi | Memperbarui bidang yang sudah ada tanpa menyisipkan yang baru. |
json_remove | Tetap NULL | Menghapus | Tidak ada aksi | Menghapus bidang. |
Indeks berbasis fungsi
Buat indeks berbasis fungsi untuk mempercepat kueri pada path JSON tertentu dalam tabel lebar.
Sintaksis
CREATE INDEX [index_name]
ON table_name (json_extract_type(column, json_path))
[INCLUDE (column_name1, ..., column_namen)]
[ASYNC]
[index_options]Parameter
| Parameter | Deskripsi |
|---|---|
index_name | Nama tabel indeks. |
table_name | Nama tabel lebar. |
json_extract_type | Fungsi ekstraksi yang mendefinisikan path yang diindeks. Fungsi yang didukung: json_extract_string, json_extract_long, json_extract_double. Jika tipe data nilai yang diekstraksi tidak sesuai dengan tipe kembalian fungsi, tidak ada indeks sekunder yang dibuat untuk baris tersebut. |
column | Nama kolom JSON. |
json_path | Path yang akan diindeks dalam kolom JSON. |
ASYNC | Membangun indeks secara asinkron. Tanpa ASYNC, indeks dibangun secara sinkron. |
Fungsi yang didukung
Fungsi berikut mendukung pembuatan indeks berbasis fungsi:
json_extract_string(json_column, 'path')— mengindeks nilai stringjson_extract_long(json_column, 'path')— mengindeks nilai integer panjangjson_extract_double(json_column, 'path')— mengindeks nilai titik mengambangjson_contains(json_column, 'value', 'path')— mengindeks pemeriksaan keberadaan; parametervaluedanpathharus berupa nilai tetap (statis)
Contoh
Buat indeks untuk mempercepat kueri json_contains pada $.roles:
CREATE INDEX idx_user_role ON test_table (json_contains(data, '"admin"', '$.roles')) INCLUDE(data) SYNC;Buat indeks pada bidang string di $.address.city:
CREATE INDEX idx_user_city ON test_table (json_extract_string(data, '$.address.city')) INCLUDE(data) SYNC;Buat indeks pada bidang string tanpa menyertakan kolom tambahan:
CREATE INDEX idx_user_city ON test_table (json_extract_string(data, '$.address.city'));Buat indeks pada bidang numerik di $.age:
CREATE INDEX idx_user_age ON test_table (json_extract_long(data, '$.age')) INCLUDE(data) SYNC;Verifikasi bahwa indeks telah dibuat:
SHOW INDEX FROM test_table;Untuk dukungan indeks pencarian JSON, lihat Gunakan indeks pencarian untuk tipe JSON Lindorm.
Batasan
Selalu gunakan sintaksis path JSON yang valid. Error
illegal json pathterjadi jika ekspresi path tidak valid. Untuk detail sintaksis path, lihat definisi JsonPath MySQL.Operasi JSON kompleks dapat memiliki overhead performa yang signifikan. Buat indeks berbasis fungsi untuk path yang sering dikueri.
Pemecahan masalah
| Error | Penyebab | Perbaikan |
|---|---|---|
illegal json path | Ekspresi path tidak sesuai sintaksis path JSON yang valid. | Periksa sintaksis path terhadap definisi JsonPath MySQL. |
json_contain candidate is not a valid value | Parameter candidate bukan string JSON yang valid. | Pastikan nilai kandidat diformat dengan benar sebagai string JSON. |
This query may be a full table scan and thus may have unpredictable performance | Kueri tidak dapat menggunakan indeks dan memindai seluruh tabel. | Buat indeks berbasis fungsi untuk path yang dikueri, atau tambahkan klausa LIMIT untuk mengurangi set hasil. |
Praktik terbaik
Pilih fungsi pembaruan yang tepat. Gunakan json_upsert saat kolom JSON mungkin NULL atau saat Anda membutuhkan perilaku sisip-atau-perbarui tujuan umum. Gunakan json_set saat kolom diketahui tidak NULL dan Anda menginginkan semantik yang kompatibel dengan MySQL.
Indeks path yang sering dikueri. Buat indeks berbasis fungsi pada path JSON yang muncul dalam klausa WHERE atau kondisi json_contains. Hal ini menghindari pemindaian tabel penuh dan secara signifikan meningkatkan performa kueri.
Gunakan fungsi ekstraksi bertipe untuk keamanan tipe. Gunakan json_extract_string, json_extract_long, dan json_extract_double alih-alih json_extract saat Anda membutuhkan tipe kembalian tertentu. Definisikan tipe data secara konsisten sebelum memasukkan data JSON — mencampur angka dan string numerik (misalnya angka 10 dan string "10") menyebabkan perilaku ambigu dan hasil kueri yang tidak terduga.