OPENJSON必须配合WITH子句才能将JSON数组展开为关系行,否则仅返回key/value/type三列;WITH需精确指定路径、类型及嵌套结构,路径错误或缺失AS JSON会导致NULL或截断。

OPENJSON 要求显式指定 WITH 子句才能映射字段
直接用 SELECT * FROM OPENJSON(@json) 只能得到键值对的三列结果(key、value、type),无法自动展开 JSON 数组元素为关系行。必须配合 WITH 子句声明目标列名、数据类型和 JSON 路径,SQL Server 才会把每个数组项解析成一行。
常见错误是漏写 WITH,或路径写成 '$.items[0].name' 这种固定下标——这只会取第一个元素,不是“映射整个数组”。
-
WITH中的路径默认以$为根,对数组而言就是遍历每一项,无需写索引 - 若 JSON 是顶层对象包裹数组(如
{"data": [...]}),路径需写成'$.data' AS JSON先提取数组,再嵌套一次OPENJSON - 字符串字段记得加
AS JSON标识嵌套结构,否则会被当作文本截断
处理嵌套 JSON 对象时,WITH 中路径必须精确匹配层级
比如 JSON 数组中每个元素含 {"user": {"id": 1, "profile": {"email": "a@b.com"}}},想取出 user.id 和 user.profile.email,WITH 必须写成:
WITH (
UserId INT '$.user.id',
Email NVARCHAR(100) '$.user.profile.email'
)路径不能简写为 '$.id' 或漏掉中间层级。SQL Server 不做字段名模糊匹配,路径错一位就返回 NULL。
- 路径支持通配符
$[*].field,但仅限顶层数组;嵌套数组需先用外层OPENJSON提取,再对value列二次解析 - 日期字段建议用
DATETIME2类型 +'$.date'路径,避免因格式不统一转成字符串 - 数值字段若可能为
null或空字符串,类型选INT比INT '$.x' DEFAULT 0更安全——后者在值为""时仍报错
性能关键:大 JSON 数组要避免多次 OPENJSON 嵌套调用
一个含 10000 个对象的 JSON 数组,如果对每个对象再调用一次 OPENJSON 解析其内部数组(比如 "tags": ["a","b"]),实际会触发 10000 × N 次解析,CPU 和内存开销陡增。
- 优先用
AS JSON把嵌套数组整体作为NVARCHAR(MAX)字段取出,后续用应用层或标量函数处理 - 真需要展开多级,改用
CROSS APPLY分两步:第一步展开外层数组,第二步对每行的value列再OPENJSON - SQL Server 2016+ 的
OPENJSON不支持并行执行,单次调用解析超 5MB JSON 时明显变慢,建议前置拆分
NULL 值和缺失字段的默认行为容易误判
OPENJSON 默认把缺失字段、null 值、空字符串都转成 SQL 的 NULL,且不报错。表结构若设了 NOT NULL 约束,插入时直接失败;若没设,业务逻辑可能拿不到预期默认值。
- 用
DEFAULT子句可覆盖:例如Name NVARCHAR(50) '$.name' DEFAULT 'Unknown' - 但
DEFAULT对JSON null无效,只对路径不存在或value为NULL生效;要区分null和缺失,得靠应用层或额外判断type列 - 布尔值 JSON 写
true/false,SQL Server 会转成1/0,类型必须声明为BIT,写INT也能存但语义不清
实际映射最常卡在路径写错和嵌套层级没拆开,而不是语法不会——盯着 F12 看一眼原始 JSON 结构,手写路径比凭记忆靠谱。

















