MySQL JSON sütun özelliği null kontrol edilir?

Aug 25 2020

MySQL 8.0.21 ile çalışıyorum. JSON sütun tipiyle çalışan bir sorgu yazmam gerekiyor. JSON belgelerinin içindeki bazı verilerin boş değerleri var ve bu boş değerleri filtrelemek istiyorum.

Olası satır örnekleri, JSON belgesindeki çoğu özellik basitlik amacıyla kaldırılmıştır:

jsonColumn
'{"value":96.0}'
'{"value":null}' -- This is the row I am trying to filter out
NULL

İşte denediğim şey:

-- Removed columns where jsonColumn was NULL but, NOT columns where jsonColumn->'$.value' was null. SELECT * FROM <table> WHERE jsonColumn->'$.value' IS NOT NULL;

-- Note the unquote syntax, ->>. The code above uses ->.
-- Produced the same result as the code above.
SELECT * 
FROM <table>
WHERE jsonColumn->>'$.value' IS NOT NULL; -- Produced same result as the two above. Not surprised because -> is an alias of JSON_EXTRACT SELECT * FROM <table> WHERE JSON_EXTRACT(jsonColumn, '$.value') IS NOT NULL;

-- Produced same result as the three above. Not surprised because ->> is an alias of JSON_EXTRACT
SELECT * 
FROM <table>
WHERE JSON_UNQUOTE(JSON_EXTRACT(jsonColumn, '$.value')) IS NOT NULL; -- Didn't really expect this to work. It didn't work. For some reason it filters out all records from the select. SELECT * FROM <table> WHERE jsonColumn->'$.value' != NULL;

-- Unquote syntax again. Produced the same result as the code above.
SELECT *
FROM <table>
WHERE jsonColumn->>'$.value' != NULL; -- Didn't expect this to work. Filters out all records from the select. SELECT * FROM <table> WHERE JSON_EXTRACT(jsonColumn, '$.value') != NULL;

-- Didn't expect this to work. Filters out all records from the select.
SELECT *
FROM <table>
WHERE JSON_UNQUOTE(JSON_EXTRACT(jsonColumn, '$.value')) != NULL; -- I also tried adding a boolean value to one of the JSON documents, '{"test":true}'. These queries did not select the record with this JSON document. SELECT * FROM <table> WHERE jsonColumn->'$.test' IS TRUE;
SELECT * 
FROM <table>
WHERE jsonColumn->>'$.test' IS TRUE;

Fark ettiğim birkaç ilginç şey ...

Diğer değerleri karşılaştırmak işe yaradı. Örneğin...

-- This query seems to work fine. It filters out all records except those where jsonColumn.value is 96.
SELECT *
FROM <table>
WHERE jsonColumn->'$.value' = 96;

Yukarıdaki örneklerin bazılarının yorumlarında bahsedilen bir başka ilginç şey, boş kontroller için bazı garip davranışlardı. Eğer jsonColumn null ise, jsonColumn -> '$. Değer'e eriştiğimi bilsem bile boş kontroller kaydı filtreleyecektir.

Bunun açık olup olmadığından emin değilim, bu yüzden biraz detaylandırmama izin verin ...

-- WHERE jsonColumn->>'$.value' IS NOT NULL
jsonColumn
'{"value":96.0}'
'{"value":null}' -- This is the row I am trying to filter out. It does NOT get filtered out.
NULL -- This row does get filtered out.

Bu gönderiye göre , - >> ve JSON_UNQUOTE & JSON_EXTRACT ile IS NOT NULL karşılaştırmalarının kullanılması işe yaramalıydı. O zamanlar işe yaradığını varsayıyorum.

Dürüst olmak gerekirse, böyle hissetmek, IS ifadesi ve JSON sütun türü ile ilgili bir hata olabilir. JSON belgesinin değerleri yerine JSON belgesiyle karşılaştırıldığı hallerde tuhaf bir davranış var.

Her şeye rağmen, bunu başarmanın bir yolu var mı? Yoksa doğru şekilde onaylamaya çalıştığım yollar mı ve bu sadece bir hata mı?

Yanıtlar

1 Tyler Aug 25 2020 at 22:12

Barmar'ın yorumunun ardından ...

Görünüşe göre bu, 8.0.13'ten önce bir süre değişti. forums.mysql.com/read.php?176,670072,670072

Forum gönderisindeki bir geçici çözüm JSON_TYPE kullanıyor gibi görünüyor. Görünüşe göre korkunç bir geçici çözüm tbh.

SET @doc = JSON_OBJECT('a', NULL);
SELECT JSON_UNQUOTE(IF(JSON_TYPE(JSON_EXTRACT(@doc,'$.a')) = 'NULL', NULL, JSON_EXTRACT(@doc,'$.a'))) as C1,
JSON_UNQUOTE(JSON_EXTRACT(@doc,'$.b')) as C2;

Forum gönderisinde (geçici çözümden önce gönderilen kodla ilgili) ...

C2 etkin bir şekilde NULL olarak ayarlanır, ancak C1, 4 karakterli 'boş' dizge olarak döndürülür.

Bu yüzden dizi karşılaştırmalarıyla uğraşmaya başladım ...

// This filtered out NULL jsonColumn but, NOT NULL jsonColumn->'$.value'
SELECT *
FROM <table>
WHERE jsonColumn->'$.value' != 'null'; jsonColumn '{"value":96.0}' '{"value":"null"}' -- Not originally apart of my dataset but, this does get filtered out. Which is very interesting... '{"value":null}' -- This does NOT get filtered out. NULL -- This row does get filtered out. // This filtered out both NULL jsonColumn AND NULL jsonColumn->'$.value'
SELECT *
FROM <table>
WHERE jsonColumn->>'$.value' != 'null';

jsonColumn
'{"value":96.0}'
'{"value":"null"}' -- Not originally apart of my dataset but, this does get filtered out.
'{"value":null}' -- This does get filtered out.
NULL -- This row does get filtered out.