You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL 14中NOT IN与!= ANY的差异及jsonb更新失效问题

PostgreSQL 14中JSONB数组过滤:!= ANY失效而NOT IN生效的原因

问题场景

我在PostgreSQL 14中编写了一条更新JSONB字段、移除指定ID元素的SQL语句:

UPDATE types
SET elements = (
    SELECT
        CASE
            WHEN jsonb_agg(element_obj) IS NULL THEN
                '[]'::JSONB
            ELSE
                jsonb_agg(element_obj)
        END
     FROM jsonb_array_elements(elements) AS t(element_obj)
     WHERE element_obj ->> 'id' != ANY(element_ids::TEXT[])
)
WHERE id = ANY(type_ids)

执行前elements字段值:

[
   {"id": "260c7f69-bc8c-49c2-b65b-cb895da3aa2a", "type": 1},
   {"id": "7e3211cb-8919-4941-b3d1-a7524493b03a", "type": 12}, 
   {"id": "c4816652-ec62-4f83-aebd-1ec468d1d4a3", "type": 6}
]

输入参数:

element_ids := ARRAY [
    '260c7f69-bc8c-49c2-b65b-cb895da3aa2a',
    '7e3211cb-8919-4941-b3d1-a7524493b03a'
]::TEXT[]

执行后字段值未发生变化,但将!= ANY替换为NOT IN后语句正常生效。

核心原因:!= ANY与NOT IN的逻辑差异

PostgreSQL中,这两个运算符的语义完全不同:

  • != ANY(array):只要数组中存在至少一个元素与当前值不相等,条件就返回true。
    比如对于要移除的ID260c7f69-bc8c-49c2-b65b-cb895da3aa2a,数组中存在另一个ID7e3211cb-8919-4941-b3d1-a7524493b03a,满足当前ID != 这个元素,因此!= ANY条件为true,该元素不会被过滤,最终被保留在聚合结果中。
  • NOT IN(array):只有当前值不在数组的所有元素中,条件才返回true。
    对于要移除的ID,它存在于数组中,因此NOT IN条件为false,元素会被过滤,符合预期。

等价替代写法

除了NOT IN,还可以使用<> ALL(array),它的语义和NOT IN完全一致,也能达到预期效果:

WHERE element_obj ->> 'id' <> ALL(element_ids::TEXT[])

内容的提问来源于stack exchange,提问作者Prosto_Oleg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 01:15:39