d11*_*wtq 8 postgresql database-design constraints
我们有一个表格,它有一个独特的约束,用于从一个用户留下的反馈,另一个与销售相关的反馈.
ALTER TABLE feedback
ADD CONSTRAINT unique_user_subject_and_sale
UNIQUE (user_id, subject_id, sale_id)
Run Code Online (Sandbox Code Playgroud)
这可以确保我们不会意外地获得重复的反馈行.
目前,我们有时会硬错误地删除错误的反馈并让用户再次离开.我们想要更改为软删除:
ALTER TABLE feedback
ADD COLUMN deleted_at timestamptz
Run Code Online (Sandbox Code Playgroud)
如果deleted_at IS NOT NULL
,考虑删除反馈,虽然我们仍然在我们的数据库中有审计跟踪(并且可能会向网站管理员显示幻像).
当我们使用像这样的软删除时,我们如何保持我们的唯一约束?是否可以在不使用更一般的CHECK()
约束的情况下进行聚合检查(我从未尝试过使用像这样的检查约束).
这就像我需要在约束中附加一个WHERE子句.
Mik*_*ll' 17
您的独特索引,后来被删除了.
CREATE UNIQUE INDEX feedback_unique_user_subject_and_sale_null
ON feedback(user_id, subject_id, sale_id)
WHERE deleted_at IS NULL
Run Code Online (Sandbox Code Playgroud)
您的独特索引至少有两个可能导致您遇到麻烦的副作用.
primary key
或unique
.例
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
Run Code Online (Sandbox Code Playgroud)
PostgreSQL将这种索引记录为部分索引,如果有时需要谷歌它.其他平台使用不同的术语 - 过滤索引是一个.您可以使用一对部分索引在一定程度上限制问题.
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
Run Code Online (Sandbox Code Playgroud)
但我认为没有理由去解决这个问题,特别是考虑到外键的潜在问题.如果你的表看起来像这样
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)
);
Run Code Online (Sandbox Code Playgroud)
那么你所需要的就是对{user_id,subject_id,sale_id}的唯一约束.您可以进一步考虑使所有删除使用"deleted_at"列而不是进行硬删除.
尽管PostgreSQL文档建议不要使用唯一索引而不是约束(如果要点有约束),看起来你可以做
CREATE UNIQUE INDEX feedback_unique_user_subject_and_sale
ON feedback(user_id, subject_id, sale_id)
WHERE deleted_at IS NULL
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4920 次 |
最近记录: |