我有两个表来处理附件:

  • "文件",其中包含id和其他信息
  • "附件",它包含id_file(表files中的id是外键)和附件的其他信息.

两个表能够共享一个文件,而不会在服务器上复制该文件(供您参考).

当我删除附件时,我只想在没有指向其id的附件的情况下删除该文件.

我有此请求,删除链接到特定项目的所有附件(表TABLE_NAME的第26项:

WITH deleted_files AS (
  DELETE FROM public.attachments a
  WHERE a.id_in_table = 26
    AND a.table_name = 'TABLE_NAME'
  RETURNING id_file
)
DELETE FROM public.files f
WHERE f.id IN (SELECT id FROM deleted_files)
  AND NOT EXISTS (
    SELECT 1
    FROM public.attachments a
    WHERE a.id_file = f.id
);

问题是:

  • 附件被正确删除,但文件没有被删除
  • 如果我再次运行相同的请求,则不会删除任何内容(这是正常的)
  • 如果我用第一个删除返回的ids运行第二个DELETE,它们将被正确删除.

是否存在某种机制来保留表的浅层副本和已删除的项,从而使删除项变得不可能?

推荐答案

就像the documentation说的,

WITH中的子语句彼此并与主查询同时执行.因此,在WITH中使用数据修改语句时,指定的更新实际发生的顺序是不可预测的.所有语句都使用相同的快照执行(请参见Chapter 13),因此它们不能"看到"彼此对目标表的影响.这减轻了行更新的实际顺序的不可预测性的影响,并意味着RETURNING数据是在不同的WITH子语句和主查询之间传达更改的唯一方式.

我的建议是运行两条不同的DELETE条语句.如果您需要它们共享相同的快照,请在REPEATABLE READ事务中运行它们.如果使用单个语句的原因是约束,则可以改用延迟约束.对第一条语句删除的行使用临时表.

Sql相关问答推荐

如何在VB.NET中使用MS SYS根据开始和结束期间日期进行查询

我如何计算字母a出现的字符串的次数?

为表中每个缺少的引用创建新行

retrofit AWS Athena中的JSON

更新其组的日期字段值小于最大日期减go 天数的记录

使用SQL创建列出两个时间戳之间小时数的列

PostgreSQL:按小时查看调整日期

根据最大值为字母数字大小写分配数值

Oracle中的时间戳

Oracle PL/SQL:解决DBMS输出大小限制的问题

从重复值中获取最新值

DB2 SQL查询结果多余数据

具有多个表 JOINS 的 STRING_AGG 的替代方法 (SQL Server 2016)

特殊条件计算小计

按所选的值将记录分组到不同的列中

在给定的日期范围内填写缺失的日期

如何在 PL/SQL 中区分返回的 XML 值?

创建一个将层次 struct 级别放入列中的查询

SQL中所有先前日期的累计总和

如何优化sql请求?