MySql-8 JSON_TABLE
function を使用すると、JSONデータをテーブルのように処理できます。
これを使用して、生成されたテーブルを使用して一時テーブルにデータを入力しようとしていますが、バグが発生していると思います。
Null値がINT NULL
列に挿入されると、次のエラーがスローされます:Invalid JSON value for CAST to INTEGER from column quantity at row 1
これが問題のコードです
DROP TABLE IF EXISTS json_temp_table;
CREATE TEMPORARY TABLE json_temp_table (
item_id int NOT NULL PRIMARY KEY,
model_number varchar(100),
quantity int NULL
)
ENGINE = INNODB
SELECT
json_tb.item_id,
json_tb.model_number,
json_tb.quantity
FROM JSON_TABLE
(
'[{"item_id":1,"model_number":"MFJA53","quantity":4},{"item_id":2,"model_number":"HSRHJN5","quantity":null},{"item_id":3,"model_number":"FAFAF1","quantity":345}]'
, "$[*]"
COLUMNS
(
item_id int PATH "$.item_id",
model_number varchar(100) PATH "$.model_number",
quantity int PATH "$.quantity"
)
) json_tb;
SELECT
*
FROM json_temp_table
Jsonで生成されたテーブルで一時テーブルにnullを挿入する方法はありますか?
奇妙な部分は、selectステートメントが挿入なしで正常に機能することです。また、一時テーブル自体は間違いなくnull int値を処理できます。これら2つが混ざらない理由がわかりません。
解決策は、nullにするプロパティを省略することです。
しばらく検索したところ、1年以上前に このバグレポート が見つかりました。これは、値NULLを含むjson文字列が実際には値であり、nullではないことを説明しています。
{"item":1,"quantity":4}
->アイテム= 1、数量= 4
{"item":1,"quantity":null}
->アイテム= 1、数量= 'null'(ある種の不親切なjson null)
{"item":1}
->アイテム= 1、数量= NULL(古き良きSQLのnull!)
これを見た後、「この非友好的なjson nullをNice nullにキャストする方法があるはずだ」と思いました。うまくいったことをたくさん試しましたが、一時テーブルに挿入できるものはありませんでした。
これは私の上で述べたことに基づいて、うまくいくはずの私の最後の試みでした。インラインのIF
ステートメントを使用して値がnullであるかどうかを検出し、実際のSQL NULL
をSIGNED
intにキャストしようとしています。値を選択する方法を示しますが、何らかの理由で値を挿入することは不可能です。
コード自体:
DROP TABLE IF EXISTS json_temp_table;
CREATE TEMPORARY TABLE json_temp_table (
item_id int NOT NULL PRIMARY KEY,
model_number varchar(100),
quantity int NULL
)
ENGINE = INNODB;
INSERT INTO json_temp_table
SELECT X.item_id,X.model_number,CAST(IF(x.quantity_is_null=1,NULL, X.quantity) AS SIGNED) 'quantity' FROM (
SELECT
json_tb.item_id,
json_tb.model_number,
json_tb.quantity,
if(json_type(json_extract(JSON_OBJECT('b',json_tb.quantity),'$.b')) = 'NULL',1 ,0) 'quantity_is_null'
FROM JSON_TABLE
(
'[{"item_id":1,"model_number":"MFJA53","quantity":4},{"item_id":2,"model_number":"HSRHJN5","quantity":null},{"item_id":3,"model_number":"FAFAF1","quantity":345}]'
, "$[*]"
COLUMNS
(
item_id int PATH "$.item_id",
model_number varchar(100) PATH "$.model_number",
quantity int PATH "$.quantity"
)
) json_tb) x;
CLI mysqlクライアントで実行
mysql> DROP TABLE IF EXISTS json_temp_table;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> CREATE TEMPORARY TABLE json_temp_table (
-> item_id int NOT NULL PRIMARY KEY,
-> model_number varchar(100),
-> quantity int NULL
-> )
-> ENGINE = INNODB;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT X.item_id,X.model_number,CAST(IF(x.quantity_is_null=1,NULL, X.quantity) AS SIGNED) 'quantity' FROM (
-> SELECT
-> json_tb.item_id,
-> json_tb.model_number,
-> json_tb.quantity,
-> if(json_type(json_extract(JSON_OBJECT('b',json_tb.quantity),'$.b')) = 'NULL',1 ,0) 'quantity_is_null'
-> FROM JSON_TABLE
-> (
-> '[{"item_id":1,"model_number":"MFJA53","quantity":4},{"item_id":2,"model_number":"HSRHJN5","quantity":null},{"item_id":3,"model_number":"FAFAF1","quantity":345}]'
-> , "$[*]"
-> COLUMNS
-> (
-> item_id int PATH "$.item_id",
-> model_number varchar(100) PATH "$.model_number",
-> quantity int PATH "$.quantity"
-> )
-> ) json_tb) x;
+---------+--------------+----------+
| item_id | model_number | quantity |
+---------+--------------+----------+
| 1 | MFJA53 | 4 |
| 2 | HSRHJN5 | NULL |
| 3 | FAFAF1 | 345 |
+---------+--------------+----------+
3 rows in set, 1 warning (0.00 sec)
mysql> INSERT INTO json_temp_table
-> SELECT X.item_id,X.model_number,CAST(IF(x.quantity_is_null=1,NULL, X.quantity) AS SIGNED) 'quantity' FROM (
-> SELECT
-> json_tb.item_id,
-> json_tb.model_number,
-> json_tb.quantity,
-> if(json_type(json_extract(JSON_OBJECT('b',json_tb.quantity),'$.b')) = 'NULL',1 ,0) 'quantity_is_null'
-> FROM JSON_TABLE
-> (
-> '[{"item_id":1,"model_number":"MFJA53","quantity":4},{"item_id":2,"model_number":"HSRHJN5","quantity":null},{"item_id":3,"model_number":"FAFAF1","quantity":345}]'
-> , "$[*]"
-> COLUMNS
-> (
-> item_id int PATH "$.item_id",
-> model_number varchar(100) PATH "$.model_number",
-> quantity int PATH "$.quantity"
-> )
-> ) json_tb) x;
ERROR 3156 (22018): Invalid JSON value for CAST to INTEGER from column quantity at row 1
mysql>