应使用json类型列而非varchar/text,mysql自动校验合法性;建表需用json类型且引擎为innodb;插入优先用json_object/json_array函数;查询区分->(返回json)和->>(返回标量);更新用json_set等函数;合理权衡json与关联表适用场景。

直接用 JSON 类型列,而不是 VARCHAR 或 TEXT;否则你只是在存字符串,不是在用 MySQL 的 JSON 能力。
创建表时声明 JSON 列必须用 JSON 类型
MySQL 会自动校验写入内容是否为合法 JSON,非法格式(如单引号、尾随逗号、键名没引号)直接报错,不会入库。这一步就卡住了大量脏数据。
-
JSON列不能设默认值(DEFAULT不被允许),也不能加NOT NULL约束后不给值——插入时必须显式传NULL或合法 JSON - 建表语句里写
details JSON,不是details TEXT;哪怕你只打算存{"a":1}这种简单结构,类型也必须是JSON - 引擎必须是
InnoDB(MyISAM不支持JSON类型)
插入数据优先用 JSON_OBJECT / JSON_ARRAY 构造
手写 JSON 字符串容易出错,尤其含变量时易拼错引号或转义。函数方式由 MySQL 内部生成,天然合法且可读性高。
INSERT INTO users (profile) VALUES (JSON_OBJECT('name', 'Alice', 'active', true, 'tags', JSON_ARRAY('dev', 'mysql')));- 避免:
INSERT INTO users (profile) VALUES ('{"name": "Alice", "active": true, "tags": ["dev", "mysql"]}');—— 看似一样,但一旦字段值含单引号或换行,就可能失败 -
JSON_OBJECT会自动去重键名、标准化布尔值(true→true,不是1),而手写字符串不会
查询时别混淆 -> 和 ->> 操作符
前者返回带引号的 JSON 片段(类型仍是 JSON),后者返回无引号的标量值(字符串/数字/布尔),直接影响后续比较和索引使用。
-
SELECT data->'$.status' FROM logs;返回"active"(带双引号,类型 JSON) -
SELECT data->>'$.status' FROM logs;返回active(纯字符串,可直接用于WHERE或ORDER BY) - 想走索引?必须用
->>提取后再建生成列,->返回的是 JSON 类型,无法直接索引 - 嵌套路径如
$.address.city、数组索引如$.tags[0]都支持,但路径错误(如键不存在)时->返回NULL,->>也返回NULL,不会报错
更新 JSON 内容必须用 JSON_SET / JSON_REPLACE / JSON_INSERT
不能用 UPDATE ... SET json_col = '...' + old_value 拼接,那会强制全量覆盖,丢失并发修改、性能差、还可能破坏二进制结构。
-
JSON_SET(data, '$.status', 'archived'):存在则更新,不存在则新增 -
JSON_REPLACE(data, '$.status', 'archived'):仅当路径已存在才更新,否则静默忽略 -
JSON_INSERT(data, '$.meta.created_by', 'system'):仅当路径不存在才插入,已存在不覆盖 - 所有函数都返回新 JSON 值,需配合
UPDATE ... SET col = JSON_SET(col, ...)使用 - 一次调用可处理多个路径:
JSON_SET(col, '$.a', 1, '$.b.c', 'x')
真正难的不是语法,而是判断什么时候该用 JSON、什么时候该拆成关联表——比如用户标签频繁增删查改,用 JSON 数组加多值索引很合适;但订单商品明细涉及金额计算和事务一致性,还是得走正规外键表。别因为“能存”就滥用。











