跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

MySQL触发器如何处理JSON字段的局部更新_利用JSON函数提取

JSON_EXTRACT在触发器中需前置JSON_VALID校验,用->>或JSON_UNQUOTE去引号,数字字段建议显式CAST,JSON比对须提取路径后类型一致比较。 触发器里直接用
JSON_EXTRACT
提取 JSON 字段局部值是可行的,但必须绕过类型校验和空值陷阱,否则触发器会中断执行。 为什么
JSON_EXTRACT(NEW.json_col, '$.key')
在触发器里常报错 MySQL 5.7 要求
JSON_EXTRACT
的第一个参数必须是合法 JSON 类型值,而
NEW.json_col
实际上是
TEXT
或
VARCHAR
类型(即使列定义为
JSON
,在触发器上下文中也可能未被自动强转)。一旦字段为空、含非法字符或只是普通字符串,就会触发
Invalid JSON text
错误,导致整个触发器失败。
JSON_VALID(NEW.json_col)
必须前置判断,不能省略 若列定义为
JSON
但内容来自旧应用或迁移数据,仍可能存非 JSON 值(如
'null'
字符串而非真正的
NULL
)
JSON_EXTRACT
对路径错误或键不存在不报错,但返回
NULL
;若后续赋值给非空列,会引发插入失败
JSON_EXTRACT
返回值带引号,直接赋值会出问题
JSON_EXTRACT
返回的是 JSON 类型值,比如
"john"
(带双引号),不是字符串
john
。如果把它直接赋给
VARCHAR
列,MySQL 5.7 默认会保留引号,导致业务层看到的是
"john"
而非预期的
john
。 php版微信js-sdk支付接口类 php版微信js-sdk支付接口类 下载 必须用
JSON_UNQUOTE(JSON_EXTRACT(...))
去掉外层引号 或者改用
->>
操作符(等价于
JSON_UNQUOTE(JSON_EXTRACT(...))
),写法更短:
NEW.json_col->>'$.name'
对数字字段(如
age
),
JSON_EXTRACT
返回的是 JSON 数字,MySQL 会隐式转为整数,但建议显式
CAST(... AS UNSIGNED)
避免边界异常(如
-0
、科学计数法) UPDATE 触发器中安全比对 JSON 内部字段是否变更 不能写
OLD.json_col != NEW.json_col
—— 这是字符串比较,顺序、空格、换行都影响结果,且无法识别语义等价的 JSON(如
{"a":1}
和
{"a": 1}
)。 应提取具体路径并分别比对:
JSON_UNQUOTE(OLD.json_col->>'$.status') != JSON_UNQUOTE(NEW.json_col->>'$.status')
注意两边都用
->>
或都用
JSON_UNQUOTE(JSON_EXTRACT())
,保持类型一致 若字段可能为
NULL
,需用
IS NULL
/
IS NOT NULL
显式判断,避免
NULL != 'x'
返回
NULL
(即 false) 数组或嵌套对象变更监控不推荐在触发器里做——性能差且逻辑复杂;只盯关键标量字段(
status
、
price
、
updated_by
)更实际 BEFORE INSERT/UPDATE 中解析 JSON 并填充生成列或普通列 典型场景:用户提交
profile
JSON,想自动拆出
nickname
和
email
存到对应列,便于索引和查询。 必须包裹在
IF JSON_VALID(NEW.profile) THEN ... END IF;
中
SET NEW.nickname = NEW.profile->>'$.nickname';
是最简写法;若路径可能缺失,加
IFNULL(..., '')
防止
NULL
写入非空列 不要在触发器里对本表做
SELECT
或
UPDATE
—— 所有操作只能基于
NEW
和
OLD
行数据 大 JSON(>4KB)频繁解析会影响触发器性能;若字段更新频率低但解析开销高,可考虑延迟处理(如通过应用层或异步任务)

相关文章