「MySQL道普請便り」
JSON型のデータを扱う上での悩みの1つは、JSON形式であれば、内容にかかわらず更新処理が成功してしまう点です。通常はアプリケーション側でバリデーションを行うことが多いと思いますが、実はSQLだけで構造をチェックすることも可能です。
今回は、MySQLでJSONデータを扱う際に、特定のスキーマ形式のデータだけを受け入れたい場合に便利なJSON_
サンプルデータの準備
今回は実際にJSON_
mysql> CREATE TABLE json_test ( id INT AUTO_INCREMENT PRIMARY KEY, payload JSON );
idはautoincrementなプライマリキー、payloadには正常または不正なJSONデータが入る想定です。このテーブルに、以下のように正常なJSONデータと不正なJSONデータを挿入します。正常な形式はname
-- 正常なJSONデータ
INSERT INTO json_test (payload) VALUES ('{ "name": "Alice", "age": 25 }'),('{ "name": "Bob", "age": 30 }');
-- age が文字列(型違い)
INSERT INTO json_test (payload) VALUES
('{ "name": "Charlie", "age": "twenty" }');
-- name が存在しない
INSERT INTO json_test (payload) VALUES
('{ "age": 40 }');
-- age が NULL
INSERT INTO json_test (payload) VALUES
('{ "name": "Eve", "age": null }');
-- フィールドがない
INSERT INTO json_test (payload) VALUES
('{}');
今回は、上記のようなJSONデータを扱ってJSON_
JSON_SCHEMA_VALID関数
JSON_
それでは、具体的な使用例を見てみましょう。
mysql> SELECT id, JSON_SCHEMA_VALID('{ "type": "object", "properties": { "name": { "type": "string" }, "age": { "type": "integer", "minimum": 0 } }, "required": ["name", "age"] }', payload) as valid FROM json_test; +----+-------+ | id | valid | +----+-------+ | 1 | 1 | | 2 | 1 | | 3 | 0 | | 4 | 0 | | 5 | 0 | | 6 | 0 | +----+-------+ 6 rows in set (0.00 sec)
この結果から、JSON_{"name": "文字列", "age": 数値}
というスキーマに適合しないデータ
JSON_SCHEMA_VALID関数の構文と動作
JSON_
JSON_SCHEMA_VALID(json_schema, json_document)
- json_
schema:JSON Schema (Draft 4形式) を文字列として指定します。 - json_
document:検証対象のJSONオブジェクトを指定します。
返り値は以下のようになります。
- スキーマに適合している場合:1
- 適合していない場合:0
- いずれかの引数が NULL の場合:NULL
なお、引数のどちらかが不正なJSON形式である場合は、関数の実行時にエラーが発生します。MySQL 8.
また、この関数はrequired属性にも対応しており、特定のプロパティの存在を必須とするルールをスキーマに含めることで、より厳密な検証が可能です。
JSON_SCHEMA_VALID関数で変数を使ったスキーマ定義を行う
JSONスキーマの定義は、変数に格納して使用することも可能です。たとえば、以下のように@schema変数にスキーマを定義し、それを JSON_
mysql> SET @schema = '{ "type": "object", "properties": { "name": { "type": "string" }, "age": { "type": "integer", "minimum": 0 } }, "required": ["name", "age"] }'; mysql> SELECT id, JSON_SCHEMA_VALID(@schema, payload) as valid FROM json_test; +----+-------+ | id | valid | +----+-------+ | 1 | 1 | | 2 | 1 | | 3 | 0 | | 4 | 0 | | 5 | 0 | | 6 | 0 | +----+-------+ 6 rows in set (0.00 sec)
JSON_VALID関数との違い
似た関数として、第211回
一方、JSON_
JSON_SCHEMA_VALID関数はCHECK制約で使える?
JSON_
このように、JSON_
mysql> CREATE TABLE json_checked ( -> id INT AUTO_INCREMENT PRIMARY KEY, -> data JSON, -> CHECK (JSON_SCHEMA_VALID(@schema, data) = 1) -> ); ERROR 3816 (HY000): An expression of a check constraint 'json_checked_chk_1' cannot refer to a user or system variable.
mysql> CREATE TABLE json_checked ( -> id INT AUTO_INCREMENT PRIMARY KEY, -> data JSON, -> CHECK (JSON_SCHEMA_VALID('{ '> "type": "object", '> "properties": { '> "name": { "type": "string" }, '> "age": { "type": "integer", "minimum": 0 } '> }, '> "required": ["name", "age"] '> }', data) = 1) -> ); Query OK, 0 rows affected (0.03 sec)
まとめ
今回は、特定のスキーマ形式に従ったJSONデータを扱う方法として、JSON_
また、JSON_
より詳細な仕様や使用例については、公式ドキュメントのMySQL :: MySQL 8.