MySQL 5.7+ 应使用原生 JSON 类型安全存储 JSON 字符串,建表时定义为 payload JSON NOT NULL,插入合法 JSON 字符串(如 '{"user_id":1001,"tags":["pay","vip"]}'),MySQL 自动校验格式、拒绝非法 JSON(如 {"a":}),并支持 JSON_EXTRACT() 等原生函数查询;不可设默认值(除 NULL),需索引时须通过生成列实现。

MySQL 5.7+ 怎么用 JSON 类型安全存 JSON 字符串
直接用 JSON 类型,别用 VARCHAR 或 TEXT 存原始字符串。MySQL 会自动校验格式、拒绝非法 JSON,并支持原生函数查询(比如 JSON_EXTRACT)。如果字段定义成 VARCHAR(1024),插入 {"a":} 这种语法错误的 JSON 不会报错,后续查出来全是脏数据。
建表时写法示例:
CREATE TABLE logs ( id BIGINT PRIMARY KEY, payload JSON NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
-
JSON类型字段不能设默认值(除NULL),也不能加传统索引;需要索引字段内容得用生成列 + 普通索引 - 插入时传入字符串即可,MySQL 自动解析:
INSERT INTO logs VALUES (1, '{"user_id": 1001, "tags": ["pay", "vip"]}') - 如果 JSON 字符串本身含单引号,用双引号包裹整个值,或用转义 —— 但更推荐统一用双引号字符串 + 参数化语句防注入
PostgreSQL 怎么用 jsonb 实现高性能写入和查询
选 jsonb,不是 json。前者二进制存储、支持索引、去重键名、忽略空白,写入和查询都更快;后者纯文本存储,只做基础解析,几乎没人用它做业务主存。
建表建议:
CREATE TABLE events ( id SERIAL PRIMARY KEY, data jsonb NOT NULL, ts TIMESTAMPTZ DEFAULT NOW() );
- 插入前不用手动
to_jsonb(),直接传字符串或对象(如 pg driver 支持传 Python dict,自动转jsonb) - 想按 JSON 内某个字段查?建 GIN 索引:
CREATE INDEX idx_events_user_id ON events USING GIN ((data -> 'user_id')); - 批量插入时,避免逐条
INSERT。用INSERT ... VALUES (...), (...), (...)或COPY导入,性能差 10 倍以上
SQL Server 怎么处理 JSON —— 别信 ISJSON() 就万事大吉
SQL Server 2016+ 支持 JSON,但本质是字符串 + 函数解析,没有原生 JSON 类型。这意味着:插入不校验、索引靠计算列、写入快但查起来容易慢。
- 插入前务必用
ISJSON(@json_str) = 1校验,否则后续JSON_VALUE可能静默返回NULL - 如果常查
$.order_id,建持久化计算列:ALTER TABLE orders ADD order_id AS JSON_VALUE(data, '$.order_id') PERSISTED,再给它加索引 - 批量插入大量 JSON 数据时,用
OPENJSON配合WITH子句解析后插入目标表,比先插 JSON 字符串再反复解析快得多 -
FOR JSON是输出用的,不是输入用的 —— 别在INSERT里嵌套FOR JSON拼字符串,极易 SQL 注入且不可读
跨数据库写入 JSON 的三个硬约束
不同数据库对 JSON 的“宽容度”差异极大,同一段 JSON 在 MySQL 能过,在 SQL Server 可能被 ISJSON 拒绝。
- 键名必须双引号:
{"id": 1}✅,{id: 1}❌(所有数据库都拒) - 字符串值里的反斜杠要转义:路径
"C: empile.json"必须写成"C:\temp\file.json",否则 MySQL 解析失败 - 数值不能带末尾点号或
NaN/Infinity:{"price": 99.}在 PostgreSQL 报错,在 MySQL 可能转成99但丢失精度
最稳妥的做法:入库前用语言层 JSON 库序列化(如 Python json.dumps(obj, separators=(',', ':'))),别手拼字符串。多一毫秒序列化,省掉三小时排查乱码和截断问题。


















