PostgreSQL嵌套CASE WHEN处理jsonb字段语法报错解决方法
错误原因
- 第一版SQL语法错误:
CASE表达式的THEN关键字后必须直接接返回值,不允许直接嵌套WHEN分支,违反了CASE的基础语法规则,因此抛出"when"附近的语法错误。 - 第二版SQL语法错误:嵌套
CASE结构少了一层END闭合标记,外层CASE没有对应的结束标识,解析器读取到AS别名时判定语法结构不完整,因此抛出"as"附近的语法错误。 - 两版SQL共同的逻辑漏洞:一是没有覆盖
data为空字符串的无效值判断,不符合需求里的三类无效值过滤要求;二是混用->(返回jsonb类型)和->>(返回text类型)取值,会造成隐式类型转换问题;三是没有判断deliveryDate键是否存在,键缺失时取值为null会导致分支判断失效。
正确实现代码
CASE -- 前置过滤:匹配事件类型 + 排除三类无效data值 WHEN type = '${EventType.TIME_ORDERED.code}' AND data IS NOT NULL AND data::text <> '' AND data <> '{}'::jsonb THEN -- 内层分支优先取有效deliveryDate,否则取嵌套的配送时间值 CASE WHEN data ? 'deliveryDate' AND (data ->> 'deliveryDate') <> '' THEN data ->> 'deliveryDate' ELSE data -> 'deliveryTimeEarliest' ->> 'to' END -- 不满足前置条件时可根据业务需要调整默认返回值,示例返回null ELSE NULL END AS changed_delivery_date,
关键说明
- 用jsonb专属的
?操作符判断键是否存在,比直接取值判断更严谨,避免键缺失时null值干扰判断 - 所有需要取实际值的场景统一用
->>返回text类型,避免类型混用导致的隐式转换报错 - 显式增加
data::text <> ''判断,覆盖空字符串的无效场景,完全匹配需求里的三类无效值过滤要求 - 两层
CASE结构各自对应END闭合标记,别名AS写在外层CASE的END之后,完全符合PostgreSQL语法规范
内容的提问来源于stack exchange,提问作者Ludwig
相关产品推荐
相关产品推荐

