PostgreSQL遍历JSON数组列表报错:FOREACH表达式不可为null
PostgreSQL遍历JSON数组报错:FOREACH expression must not be null 排查与解决
问题场景
需要在PostgreSQL中遍历JSON数组,编写了以下PL/pgSQL代码:
do $$ declare jsn JSONB; j JSONB; arj JSONB[]; begin jsn = to_jsonb('{"lst" : [{"a":"1"}, {"b":"2"}]}'::TEXT); arj = jsn->>'lst'; FOREACH j IN ARRAY arj LOOP SELECT j; END LOOP; end; $$;
运行后触发错误:
ERROR: FOREACH expression must not be null CONTEXT: PL/pgSQL function inline_code_block line 9 at FOREACH over array SQL state: 22004
错误原因分析
- JSON解析错误:
to_jsonb('{"lst"...}'::TEXT)是把JSON格式的字符串转成了JSONB类型的字符串值,而非解析成JSONB对象。实际jsn存储的是带转义的字符串,而非预期的JSON结构,导致后续提取lst字段时返回null。 - 类型不匹配:即使
jsn是正确的JSONB对象,->>操作符返回的是TEXT类型,直接赋值给JSONB[]类型变量arj会导致隐式转换失败,最终arj为null,触发FOREACH的非空检查错误。
解决方法
提供两种可行方案:
方案一:修正解析与类型转换
先正确解析JSON为JSONB对象,再将JSON数组转为PostgreSQL原生数组:
do $$ declare jsn JSONB; j JSONB; arj JSONB[]; begin -- 直接将JSON字符串转为JSONB类型 jsn = '{"lst" : [{"a":"1"}, {"b":"2"}]}'::JSONB; -- 将JSON数组转为PostgreSQL的JSONB数组 arj = array(select jsonb_array_elements(jsn->'lst')); FOREACH j IN ARRAY arj LOOP -- 用RAISE NOTICE输出结果,DO块中SELECT不会返回给客户端 RAISE NOTICE '%', j; END LOOP; end; $$;
方案二:直接遍历JSON数组(更简洁)
无需转换为PostgreSQL数组,直接通过jsonb_array_elements函数遍历:
do $$ declare jsn JSONB; j JSONB; begin jsn = '{"lst" : [{"a":"1"}, {"b":"2"}]}'::JSONB; -- 遍历JSON数组的每个元素 FOR j IN SELECT jsonb_array_elements(jsn->'lst') LOOP RAISE NOTICE '%', j; END LOOP; end; $$;
补充说明
->操作符返回JSONB类型,->>返回TEXT类型,需根据场景选择。- DO块中的
SELECT j不会将结果返回给客户端,需用RAISE NOTICE、插入表等方式处理结果。
内容的提问来源于stack exchange,提问作者C47_C0D3R
相关产品推荐
相关产品推荐

