如果父级未被任何其他子级引用,则删除父级

2024-04-03

我有一个示例情况:parent表有一列名为id,引用于child表作为外键。

删除子行时,如果父行未被任何其他子行引用,如何同时删除父行?


在 PostgreSQL 中9.1 或更高版本您可以使用单个语句来完成此操作数据修改CTE https://www.postgresql.org/docs/current/queries-with.html#QUERIES-WITH-MODIFYING。这通常不太容易出错。它最小化两次 DELETE 之间的时间范围,其中竞争条件并发操作可能会导致令人惊讶的结果:

WITH del_child AS (
    DELETE FROM child
    WHERE  child_id = 1
    RETURNING parent_id, child_id
    )
DELETE FROM parent p
USING  del_child x
WHERE  p.parent_id = x.parent_id
AND    NOT EXISTS (
   SELECT FROM child c
   WHERE  c.parent_id = x.parent_id
   AND    c.child_id <> x.child_id   -- !
   );

fiddle https://dbfiddle.uk/z3Zi907E
Old sqlfiddle http://www.sqlfiddle.com/#!17/7e89d5/1

无论如何,孩子都会被删除。我引用手册 https://www.postgresql.org/docs/current/queries-with.html#QUERIES-WITH-MODIFYING:

数据修改语句WITH只执行一次,并且总是要完成,与主查询是否读取无关 他们的所有(或者实际上是任何)输出。请注意,这是不同的 从规则SELECT in WITH: 正如上一节所述, 执行一个SELECT仅进行到主查询 要求其输出。

仅当父级没有时才会被删除other孩子们。
请注意最后一个条件。与人们的预期相反,这是必要的,因为:

中的子语句WITH被处决同时与彼此 以及主要查询。因此,在使用数据修改时 中的陈述WITH,指定更新实际的顺序 发生的事情是不可预测的。所有语句都以相同的方式执行 快照(参见第13章 https://www.postgresql.org/docs/current/mvcc.html),所以他们无法“看到”彼此的效果 在目标表上。

大胆强调我的。
我使用了列名parent_id代替非描述性的id.

消除竞争条件

消除可能的竞争条件完全地, 锁定父行first。所有类似的操作都必须遵循相同的程序才能起作用。

WITH lock_parent AS (
   SELECT p.parent_id, c.child_id
   FROM   child  c
   JOIN   parent p ON p.parent_id = c.parent_id
   WHERE  c.child_id = 12              -- provide child_id here once
   FOR    NO KEY UPDATE                -- locks parent row.
   )
 , del_child AS (
   DELETE FROM child c
   USING  lock_parent l
   WHERE  c.child_id = l.child_id
   )
DELETE FROM parent p
USING  lock_parent l
WHERE  p.parent_id = l.parent_id
AND    NOT EXISTS (
   SELECT FROM child c
   WHERE  c.parent_id = l.parent_id
   AND    c.child_id <> l.child_id   -- !
   );

只能这样one一次事务可以锁定同一个父级。因此,不会发生多个事务删除同一父级的子级,但仍然看到其他子级并保留父级,而所有子级随后都消失的情况。 (仍然允许更新非键列FOR NO KEY UPDATE.)

如果这种情况从未发生或者您可以忍受它(几乎从未)发生 - 第一个查询会更便宜。否则,这是安全路径。

FOR NO KEY UPDATE是随 Postgres 9.4 引入的。手册中有详细说明。 https://www.postgresql.org/docs/current/explicit-locking.html#LOCKING-ROWS在旧版本中使用更强的锁FOR UPDATE反而。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果父级未被任何其他子级引用,则删除父级 的相关文章

随机推荐

  • 正则表达式匹配数字或特定字符串(即“全部”)

    这听起来很简单 但我的正则表达式知识有限 我需要一个表达式来匹配十进制数或字符串 all 就像在范围验证器中允许单词 all 代表最大范围一样 我认为这样的事情可能会起作用 d d any 但以上不适用于 任何 这是一个不使用正则表达式的解
  • .Net Framework 版本 C# 7.2 可用

    我尝试安装 net框架4 7 2 项目属性中目标框架仍然为空 我尝试运行的程序使用只读结构体 这是一部分C 7 2 你能指导我 Net Framework 版本有C 7 2 语言功能独立于 Net 版本 框架 核心 标准 您将需要使用能够理
  • OSX 状态菜单在 Swift 中不起作用

    我尝试使用 swift 将一个简单的状态菜单添加到状态栏 但它不会显示 与 Objective c 一起工作 AppDelegate h interface AppDelegate NSObject
  • 从苹果下载 iPhone 示例代码 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 iphone sdk 文档包含示例代码的链接 但您必须从网络上单独下载它们 有没有可以从苹果一次性下载的捆绑包 例如 阅读第一个 iPho
  • 当我更改配置设置时,Visual Studio 生成“Settings1.Designer.vb”

    有时 并非总是 当我在 我的项目 页面中编辑设置时 当我从那里添加一个设置或编辑一个值时 会收到错误消息 Settings is ambiguous between declaration in Modules
  • 跳进C语言的一个块

    如果我像这个例子一样跳进一个块 跳过 声明 include
  • 找到 2 个 java.sql.Timestamps 之间的小时或分钟差异?

    我存储一个java sql Timestamp in a PostgreSQL数据库为时间戳数据类型 我想找出数据库中存储的数据类型与当前数据类型之间的差异 以分钟或小时为单位 时间戳 这样做的最佳方法是什么 是否有内置方法 或者我必须将其
  • 文本背景颜色溢出

    我将背景颜色应用于国家 地区列表中的链接 总体来说效果很好 然而 对于名称较长的国家来说 它的效果不太好 我试图让黄色溢出一切并清楚地显示国家的全名 HTML div class flagList div class flagColumn
  • Jade 模板布局无法与 Node.js 结合使用

    我正在尝试在 Node js 中创建一个使用 Jade 模板和布局的简单服务器 由于某种原因 它只会加载模板而不加载布局 这是我所得到的 main js var express require express var app express
  • 如何正确使用Feature2D(如SimpleBlobDetector)? (Python + OpenCV)

    我正在尝试使用一些简单的代码运行斑点检测 img cv2 imread args image height width channels img shape params cv2 SimpleBlobDetector Params para
  • 如何绘制样本的 PMF?

    是否有任何函数或库可以帮助我绘制样本的概率质量函数 就像绘制样本的概率密度函数一样 例如 使用 pandas 绘制 PDF 就像调用以下命令一样简单 sample plot kind density 如果没有简单的方法 我如何计算 PMF
  • 有人知道 10 位原始 RGB 吗?关于全视

    我正在使用 Omnivision ov5620 http electronics123 net amazon datasheet OV5620 CLCC DS 20 1 3 pdf http electronics123 net amazo
  • NLog 在发布模式下不工作

    我正在使用 NLog 记录我的 asp net mvc C 应用程序中的异常 NLog 在发布模式下不工作 在调试模式下运行时也是如此 可能是什么问题 有什么解决办法吗 我和你遇到了同样的问题 ASP NET MVC 3 NET 4 IIS
  • OrientDB 中带有子选择的根空间查询

    我正在尝试组合一个查询来查找图中节点 2 公里以内的节点 假设我有一个数据集 标记了纳斯卡线中的一些地理符号 Name Latitude Longitude Hummingbird 14 692131 75 148892 Monkey 14
  • 如何选择哪个 iPhone 型号模拟器来运行我的 React Native 应用程序?

    我正在开发 React Native 应用程序 并在 iOS 模拟器上进行测试 但是 它始终在 iPhone 6 上运行 我不知道如何切换到其他 iPhone 型号 例如 iPhone 6 Plus 或 5 我可以通过转到模拟器 gt 硬件
  • 警告:活动未启动,其当前任务已被带到前面[重复]

    这个问题在这里已经有答案了 我觉得这个问题很常见 Stackoverflow 上的许多结果都谈到了这一点 一般的答案是 因为一个旧的应用程序正在运行 并且我尝试从 Eclipse 运行一个新的应用程序 但编译没有改变 所以 Android
  • 模板类类型别名在成员声明中无法替换

    假设你有一个模板class像这样 template
  • 如何清除“运行”->“参数”菜单中的“参数”字段?

    我正在使用 CodeGear RAD Studio IDE 为了使用命令行参数测试我的应用程序 我多次使用 运行 gt 参数 菜单中的 参数 字段 但每次我为它提供一个新值时 它都无法从 下拉框 中删除 我需要清理这个字段 删除所有值 因为
  • 在现实世界中扩展 Docker 容器

    我有一些关于扩展 Docker 容器的基本问题 我有 5 个不同的应用程序 它们彼此没有连接 在拥有容器之前 我会在每个虚拟机上运行 1 个应用程序 并在云中单独扩展和缩小它们 现在 有了容器 我就可以在虚拟机之上实现隔离 因此现在我可以运
  • 如果父级未被任何其他子级引用,则删除父级

    我有一个示例情况 parent表有一列名为id 引用于child表作为外键 删除子行时 如果父行未被任何其他子行引用 如何同时删除父行 在 PostgreSQL 中9 1 或更高版本您可以使用单个语句来完成此操作数据修改CTE https