【问题标题】:delete/select hierarchy data in postgresql在 postgresql 中删除/选择层次结构数据
【发布时间】:2016-09-11 18:14:11
【问题描述】:

我有表 comment,我想通过输入 id 删除并删除所有子项,

以下两个查询均不删除所有层次结构数据,只删除自身和一个子行...

with闭包中选择递归有什么问题吗?

评论

id | parent_comment_id
1  | 
2  | 1
3  | 2
4  |

查询 1

WITH RECURSIVE coH AS (
  SELECT co.id,
    co.id AS rootId
    FROM comment co

  UNION ALL

  SELECT coChild.id,
    coChild.parent_comment_id as parentCommentId
    FROM comment coChild
    JOIN coH coP ON coP.id = coChild.parent_comment_id
)
DELETE FROM comment WHERE id IN (
  SELECT id FROM coH WHERE rootId = $1
)

查询 2

DELETE FROM comment WHERE id IN (
  WITH RECURSIVE coH AS (
    SELECT co.id,
      co.id AS rootId
      FROM comment co

    UNION ALL

    SELECT coChild.id,
      coChild.parent_comment_id as parentCommentId
      FROM comment coChild
      JOIN coH coP ON coP.id = coChild.parent_comment_id
  )

  SELECT id FROM coH WHERE rootId = $1
)

更新

var dbQuery = `DELETE FROM comment WHERE id IN (
  WITH RECURSIVE coH (id, parentCommentId, rootId) AS (
    SELECT co.id,
      co.parent_comment_id as parentCommentId,
      co.id AS rootId
      FROM comment co

    UNION ALL

    SELECT coChild.id,
      coChild.parent_comment_id as parentCommentId,
      coP.rootId
      FROM comment coChild
      JOIN coH coP ON coP.id = coChild.parent_comment_id
  )

  SELECT id FROM coH WHERE rootId = $1
)`;

【问题讨论】:

  • 您的查询似乎是正确的,但以错误的顺序删除可能会导致外键违规。您可以通过没有外键(不推荐!)或使用 ON DELETE CASCADE 或 DEFERRABLE 的外键来解决此问题。
  • @ZiggyCrueltyfreeZeitgeister 我找到了这个答案stackoverflow.com/a/10381384/5593189我在我的问题中更新,它可以删除所有,但我不知道为什么? coH (id, parentCommentId, rootId) 支撑是什么?并在第一部分选择为什么需要co.parent_comment_id as parentCommentId
  • @ZiggyCrueltyfreeZeitgeister 我没有在评论表中设置外键。我可以设置comment.parent_comment_id fk comment.id 吗?如果该列可以为空仍然可以设置外键?

标签: sql postgresql recursion hierarchy postgresql-9.4


【解决方案1】:

保持简单,将参数放在递归的初始查询中:

with recursive cbase as (
    select 1 as id -- select $1 as id

    union all

    select child.id
    from comment as child
    join cbase on cbase.id = child.parent_comment_id
)
delete from comment 
where id in (select * from cbase)
returning id;

 id 
----
  1
  2
  3
(3 rows)

DELETE 3    

【讨论】:

  • 感谢您的回复和示例代码! select 1 as id 或`选择 $1 作为 id` ?我仍然想知道为什么我的查询不起作用,我的原始查询和更新查询有什么不同使它起作用?
  • 您的查询效果不佳,因为它消除了 where 子句中的一些行。在这种情况下,您将始终获得不超过两行。 select 1 ... 只是一个测试查询的例子,你当然应该使用select $1...
  • 我收到错误 operator does not exist: text = integer ... JOIN co ON co.id = child.parent_comment_id ??
  • var dbQuery = ` WITH RECURSIVE co AS ( SELECT $1 AS id UNION ALL SELECT child.id FROM comment AS child JOIN co ON co.id = child.parent_comment_id ) DELETE FROM comment WHERE id IN (SELECT * FROM co) 返回 id`;
  • 我用闭包更改了第一个选择,它可以工作.. ` WITH RECURSIVE co AS ( SELECT co.id AS id FROM comment co WHERE id = $1 UNION ALL SELECT child.id FROM comment AS child JOIN co ON co.id = child.parent_comment_id ) DELETE FROM comment WHERE id IN (SELECT * FROM co) RETURNING id;`
猜你喜欢
  • 1970-01-01
  • 2019-08-29
  • 1970-01-01
  • 1970-01-01
  • 2014-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多