5月27日 18:24

MariaDB 的 JSON 函数怎么用?有哪些常见坑?

MariaDB 从 10.2 开始提供了一套 JSON 函数,能直接在 SQL 里创建、查询、修改和校验 JSON 数据。JSON 列本质是 LONGTEXT 加 CHECK 约束,不是 MySQL 那种二进制格式,这一点在迁移时容易踩坑。

追问

JSON_EXTRACT、JSON_VALUE、JSON_QUERY 有什么区别?

三个都是取值,但返回类型不同:

函数返回值示例
JSON_EXTRACT原始 JSON 片段(带引号)"John"
JSON_VALUE标量值(去引号)John
JSON_QUERY对象或数组{"city":"NY"}

日常取字符串值用 -> 操作符(JSON_EXTRACT 的语法糖),取标量用 JSON_VALUE,取嵌套对象用 JSON_QUERY。

JSON_SET、JSON_INSERT、JSON_REPLACE 有什么区别?

  • JSON_SET:存在则更新,不存在则插入——万能选手
  • JSON_INSERT:只在路径不存在时插入,已有值不动
  • JSON_REPLACE:只在路径已存在时替换,没找到就跳过

记住一句话:不确定用 SET,只想加新字段用 INSERT,只想改旧字段用 REPLACE。

JSON 列怎么加索引?

JSON 列不能直接建普通索引。两种方式:

  1. 生成列 + 索引(推荐):
sql
ALTER TABLE products ADD COLUMN brand VARCHAR(50) GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(attributes, '$.brand'))) STORED, ADD INDEX idx_brand(brand);
  1. 函数索引(MariaDB 10.3+):
sql
CREATE INDEX idx_brand ON products((CAST(attributes->'$.brand' AS CHAR(50))));

MariaDB 的 JSON 和 MySQL 的 JSON 有什么区别?

这是迁移时最容易翻车的地方:

对比项MariaDBMySQL
存储格式原文 LONGTEXT二进制 JSON
JSON 类型LONGTEXT 的别名独立数据类型
自动校验需要 CHECK 约束内置校验
部分更新不支持支持二进制增量更新

MariaDB 存原文的好处是可以直接用文本函数处理,坏处是每次修改整个字段重写,大 JSON 字段更新性能差。

用 JSON 列存数据有什么坑?

  1. 没有 schema 约束:同列不同行结构可以完全不同,查出来才知道长什么样,排查问题靠蒙
  2. 查询性能:每次取值都要解析 JSON,高频查询字段务必抽成普通列加索引
  3. 更新代价:改一个字段整个 JSON 重写,大文档更新慢
  4. CHECK 约束别忘了加
sql
CREATE TABLE products ( id INT PRIMARY KEY, attrs JSON, CONSTRAINT chk_json CHECK (JSON_VALID(attrs)) );

写段代码

sql
-- 建表 + 插入 + 查询一条龙 CREATE TABLE products ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100), attrs JSON CHECK (JSON_VALID(attrs)) ); INSERT INTO products (name, attrs) VALUES ('Laptop', '{"brand":"Dell","ram":"16GB"}'); -- 查品牌、改内存 SELECT name, attrs->'$.brand' AS brand FROM products; UPDATE products SET attrs = JSON_SET(attrs, '$.ram', '32GB') WHERE id = 1;
标签:MariaDB