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

PostgreSQL仅无关联记录时按ID删行的GQL实现问题

问题

需要实现仅当指定ID的material表数据行与其他关联表无关联记录时,才按ID删除该行的逻辑。初始编写的PostgreSQL逻辑如下:

DELETE FROM material m
WHERE NOT EXISTS (
    SELECT FROM material m
    LEFT JOIN project_material pm on m.id = pm.material
    LEFT JOIN project_materialset_material pmm on m.id = pmm.material
    LEFT JOIN materialset_material mm on m.id = mm.material
    WHERE (pmm.id IS NOT NULL OR
        pm.id IS NOT NULL OR
        mm.id IS NOT NULL ) AND m.id=13
)
AND m.id=13
    
RETURNING m.id;

需要编写对应逻辑的GQL变更语句。

过程问题

尝试编写的查询无关联物料的GQL始终返回空数组[],但数据库中实际存在无关联的material数据,测试代码如下:

query M {
  material(where: {
    project_materials: {
      id: {
          _is_null: true
      }
    }
    project_materialset_materials: {
      id: {
          _is_null: true
      }
    }
    materialset_materials: {
      id: {
          _is_null: true
      }
    }
  }
  )
    {
    id
    project_materials {
      id
    }
    project_materialset_materials {
      id
    }
    materialset_materials {
      id
    }
  }
}

将where条件中的id字段替换为关联外键material字段后,查询结果依然为空。


解答

你之前的查询不生效的核心原因:从语法判断你使用的是Hasura GraphQL引擎,直接在数组关联条件中写字段_is_null: true时,引擎生成的SQL会使用内连接逻辑,无法正确匹配无关联的主表记录。判断数组关联无记录需要使用Hasura内置的_none运算符,该运算符生成的SQL就是NOT EXISTS逻辑,和你手写的删除判断完全对齐。

正确的删除mutation写法

直接将三个关联的_none: {}条件(含义为对应关联表无任何关联记录)和目标ID条件传入删除接口即可:

mutation DeleteMaterialIfNoLinks {
  delete_material(
    where: {
      id: { _eq: 13 }
      project_materials: { _none: {} }
      project_materialset_materials: { _none: {} }
      materialset_materials: { _none: {} }
    }
  ) {
    affected_rows
    returning {
      id
    }
  }
}

返回规则

  • 若affected_rows返回1:说明目标ID的物料无任何关联记录,删除成功,returning字段会返回被删除的物料ID
  • 若affected_rows返回0:说明目标ID的物料至少存在一条关联记录,不会执行删除,和你原SQL的逻辑完全一致。

如果需要先验证查询逻辑是否正确,可以先把where条件放到查询接口中测试,确认能查到对应无关联的物料ID后再执行删除即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 11:57:11