首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >排除软删除行的唯一约束

排除软删除行的唯一约束
EN

Stack Overflow用户
提问于 2012-11-07 06:28:22
回答 3查看 8.9K关注 0票数 12

我们有一个表,它有一个唯一的约束,用于一个用户留下的反馈,另一个用户关于销售的反馈。

代码语言:javascript
复制
ALTER TABLE feedback
ADD CONSTRAINT unique_user_subject_and_sale
UNIQUE (user_id, subject_id, sale_id)

这可以确保我们不会意外地得到重复的反馈行。

目前,我们有时硬删除留在错误中的反馈,并让用户再次留下它。我们想要更改为软删除:

代码语言:javascript
复制
ALTER TABLE feedback
ADD COLUMN deleted_at timestamptz

如果为deleted_at IS NOT NULL,则考虑删除反馈,尽管我们的数据库中仍有审计跟踪(并且可能会将其显示给站点管理员)。

当我们像这样使用软删除时,我们如何保持我们的独特约束呢?有没有可能在不使用更通用的CHECK()约束的情况下执行聚合检查(我从未尝试过使用这样的检查约束)。

这就像我需要在约束后面附加一个WHERE子句。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-11-07 07:04:18

你的唯一索引,后来被编辑掉了。

代码语言:javascript
复制
CREATE UNIQUE INDEX feedback_unique_user_subject_and_sale_null
ON feedback(user_id, subject_id, sale_id)
WHERE deleted_at IS NULL

您的唯一索引至少有两个副作用,可能会给您带来一些麻烦。

在其他表中,您不能设置引用“

  • ”的外键约束。外键引用需要声明为unique.

  • Your或primary key的列的某种组合,唯一索引允许多个仅在"deleted_at“时间戳上不同的行。因此,有可能得到如下示例所示的行。这是否是一个问题是application-dependent.

示例

代码语言:javascript
复制
user_id  subject_id  sale_id  deleted_at
--
1        1           1        2012-01-01 08:00:01.33
1        1           1        2012-01-01 08:00:01.34
1        1           1        2012-01-01 08:00:01.35

PostgreSQL将这种类型的索引记录为部分索引,如果您需要使用谷歌搜索它的话。其他平台对此使用不同的术语--过滤索引就是其中之一。您可以使用一对部分索引将问题限制在一定程度上。

代码语言:javascript
复制
CREATE UNIQUE INDEX feedback_unique_user_subject_and_sale_null
ON feedback(user_id, subject_id, sale_id)
WHERE deleted_at IS NULL

CREATE UNIQUE INDEX feedback_unique_user_subject_and_sale_not_null
ON feedback(user_id, subject_id, sale_id)
WHERE deleted_at IS NOT NULL

但是我认为没有理由这么麻烦,特别是考虑到外键的潜在问题。如果您的表如下所示

代码语言:javascript
复制
create table feedback (
  feedback_id integer primary key,
  user_id ...
  subject_id ...
  sale_id ...
  deleted_at ...
  constraint unique_user_subj_sale 
    unique (user_id, subject_id, sale_id)
);

那么您所需要的就是对{user_id,subject_id,sale_id}的唯一约束。您可以进一步考虑使所有删除都使用"deleted_at“列,而不是进行硬删除。

票数 26
EN

Stack Overflow用户

发布于 2012-11-07 07:03:30

尽管PostgreSQL文档建议不要使用唯一索引而不是约束(如果点要有约束),但您似乎可以这样做

代码语言:javascript
复制
CREATE UNIQUE INDEX feedback_unique_user_subject_and_sale
ON feedback(user_id, subject_id, sale_id)
WHERE deleted_at IS NULL
票数 8
EN

Stack Overflow用户

发布于 2021-11-16 15:11:30

您可以使用deleted_at签名创建约束。

代码语言:javascript
复制
ALTER TABLE feedback
ADD CONSTRAINT unique_user_subject_and_sale
UNIQUE (user_id, subject_id, sale_id, deleted_at)

这不会产生像唯一索引这样的问题。

唯一的问题是删除用户反馈,创建一个新反馈,然后在同一时间再次删除它。

考虑到柱子的精确度,用户必须适应1微秒。让我们面对它,这是不可能的,即使他完成了,这些请求之间的时间肯定会大于1微秒。

唯一的问题是null值不是唯一的。所以它不会起作用。

但是您可以为未删除的行添加一个默认值,作为您可以存储在该列中的最低值。

如果您不能接受deleted_at的默认值,如果对象没有被删除,您可以考虑添加一个deleted_token列,如果您删除了一个值,则可以为它生成一个键,对于未删除的对象,可以保留0或其他值。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13260456

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档