PostgreSQL用jsonb_array_elements()展开JSON数组并INSERT,需转为jsonb类型,用->>提取字符串并显式转类型;MySQL 8.0+用JSON_TABLE()虚拟展开;SQL Server用OPENJSON()配合WITH映射结构化列;三者均严格区分字段名大小写与空格。

PostgreSQL 中用 jsonb_array_elements() 展开 JSON 数组并 INSERT
如果你的原始数据是一段包含对象数组的 JSON 字符串(比如 '[{"name":"Alice","age":30},{"name":"Bob","age":25}]'),想批量插入到已有表 users(name text, age int),最直接的方式是用 jsonb_array_elements() 配合 INSERT ... SELECT。
注意:必须是 jsonb 类型才能用这个函数;若字段是 text 或 json,得先显式转换:::jsonb。
- 确保源 JSON 是合法数组格式,否则
jsonb_array_elements()会报错ERROR: cannot call jsonb_array_elements on a scalar - 用
->>提取字符串值(带自动类型转换),->返回jsonb,需再转类型,比如(elem->'age')::int - 如果 JSON 字段缺失某个 key(如
"age"缺失),->>返回NULL,不会报错,但要注意目标列是否允许 NULL
INSERT INTO users (name, age)
SELECT elem->>'name', (elem->>'age')::int
FROM jsonb_array_elements('[{"name":"Alice","age":30},{"name":"Bob","age":25}]'::jsonb) AS elem;
MySQL 8.0+ 使用 JSON_TABLE() 解析嵌套 JSON 批量插入
MySQL 不支持类似 PostgreSQL 的行集函数,但 8.0+ 引入了 JSON_TABLE(),可把 JSON 数组“虚拟展开”成一张临时表。它比反复调用 JSON_EXTRACT() 更可靠、更易读。
关键点:路径表达式必须匹配数组结构,列定义里的 PATH 是相对于当前数组元素的;别名(如 jt)不可省略。
-
JSON_TABLE()要求输入是合法 JSON 值,不能是未转义的字符串字面量;常见错误是漏掉引号或写成单引号包围的非 JSON 字符串 - 若原 JSON 存在深层嵌套(如
{"data":[{"name":"X"}]}),路径得写成'$.data[*]',而不是'$[*]' - 列类型必须显式声明,
VARCHAR(100)和INT不会自动推导;数值类字段若 JSON 中为字符串("25"),需用CAST(col AS UNSIGNED)
INSERT INTO users (name, age)
SELECT name, age FROM JSON_TABLE(
'[{"name":"Alice","age":30},{"name":"Bob","age":25}]',
'$[*]' COLUMNS (
name VARCHAR(100) PATH '$.name',
age INT PATH '$.age'
)
) AS jt;
SQL Server 中用 OPENJSON() 处理 JSON 并跳过解析失败项
SQL Server 的 OPENJSON() 默认以 json 列为输入,返回含 key、value、type 的结果集。配合 WITH 子句可映射为结构化列,适合批量导入。
详细的 Three.js 3D 图形参考,涵盖场景设置、相机、几何体、材质、光照、动画、控制器、加载器、数学工具和调试。
容易被忽略的是:默认模式(OPENJSON(json_string))只返回基础键值对,必须加 WITH 才能按字段名提取;且 WITH 中类型声明不匹配时(比如 JSON 里是 "30" 却声明为 INT),该行整体会被静默丢弃 —— 不报错,但数据没了。
- 用
lax模式(默认)可容忍缺失字段,strict模式下任一字段缺失即报错JSON path is not found - 若 JSON 数组中某对象有额外字段(如
"email"),只要WITH里没定义,就完全忽略,不影响其他字段解析 - 时间字段需注意格式;
"2024-01-01"可直转DATE,但"2024-01-01T12:34:56"得用DATETIME2
INSERT INTO users (name, age)
SELECT name, age
FROM OPENJSON(N'[{"name":"Alice","age":30},{"name":"Bob","age":25}]')
WITH (
name NVARCHAR(100) '$.name',
age INT '$.age'
);
通用陷阱:JSON 字段名大小写、空格、特殊字符导致 INSERT 失败
所有数据库解析 JSON 时,字段名都严格区分大小写,且不自动 trim 空格。比如 "Name" 和 "name" 是两个不同字段;" age "(前后带空格)无法用 $.age 匹配。
更隐蔽的问题是控制字符:JSON 字符串里混入不可见的 \u200b(零宽空格)或 \u00a0(NBSP),会导致路径匹配失败,但错误信息往往不提示具体位置。
- 入库前建议用正则或程序层预处理:去除首尾空白、统一 key 名大小写、替换常见非法空白符
- PostgreSQL 可用
replace(replace(json_text, '\u200b', ''), '\u00a0', '')::jsonb粗筛,但不能覆盖全部 Unicode 空格变体 - MySQL 中
JSON_VALID()只校验语法,不保证字段名可用;真正要验证,得先JSON_EXTRACT()出一个样例再检查 key 是否存在
批量解析 JSON 的难点不在语法本身,而在数据质量不可控 —— 你永远不知道上游塞进来的是不是“看起来像 JSON”的字符串。

















