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
相关产品推荐
相关产品推荐

