将复合主键限制为仅一条记录为“未删除”(其中多个“已删除”记录不调用约束)

Posted

技术标签:

【中文标题】将复合主键限制为仅一条记录为“未删除”(其中多个“已删除”记录不调用约束)【英文标题】:Limit composite primary key to only one record as "not deleted" (where multiple "deleted" records do not invoke constraint) 【发布时间】:2021-12-30 16:09:01 【问题描述】:

想要使用复合主键以限制只有一条记录可用于生产。

表:user_id text, well_id text, deleted int, [other attributes]

建议的主键:(user_id, well_id, deleted)

这里的唯一性只与一个唯一组合的记录真正相关:user_id + well_id + deleted = 0 ...

换句话说,可能有多个记录user_id + well_id + deleted = 1(删除的值只是一个删除的标记)?现在,我正在考虑定义 deleted 标记在大于 0 时表示“已删除”,因此我可以为所有已删除的记录递增。但我认为有人可能有更好的主意。

【问题讨论】:

为什么需要重复使用 ID? 无法完成。为历史记录创建一个单独的表并将它们存储在那里。 @stickybit - 需要重新获取其特定用户和特定井的 ID。 【参考方案1】:

在您的情况下,您可以使用不可变的标准 deleted = 0 来实现唯一性。

这是示例设置;

create table table1 (
  id serial primary key,
  user_id text, 
  well_id text, 
  deleted int
);

-- the index is unique only for the records which have deleted = 0 
create unique index on table1 (user_id, well_id) where deleted = 0; 
 
insert into table1 (user_id, well_id, deleted) values ('user1', 'well1', 0);
insert into table1 (user_id, well_id, deleted) values ('user1', 'well1', 1);
-- this statement doesn't throws error
insert into table1 (user_id, well_id, deleted) values ('user1', 'well1', 1);
insert into table1 (user_id, well_id, deleted) values ('user2', 'well2', 0);

select * from table1;
id user_id well_id deleted
1 user1 well1 0
2 user1 well1 1
3 user1 well1 1
4 user2 well2 0
-- Finally, this statement throws an error
insert into table1 (user_id, well_id, deleted) values ('user1', 'well1', 0);  

ERROR:  duplicate key value violates unique constraint "table1_user_id_well_id_idx"
DETAIL:  Key (user_id, well_id)=(user1, well1) already exists.

db 小提琴here

【讨论】:

最好让deleted 成为boolean。但这是正确的解决方案! 谢谢@Sahap Asci!这非常有帮助! @LaurenzAlbe - 同意布尔值...但会损害开发团队偏好的 b/c。 “开发者团队偏好”,hmpf。因此,如果他们不知道或不喜欢一种数据类型,即使它是正确的,也不会被使用?

以上是关于将复合主键限制为仅一条记录为“未删除”(其中多个“已删除”记录不调用约束)的主要内容,如果未能解决你的问题,请参考以下文章

使用 RAISE 创建触发器

Hibernate 的复合主键

SQL 更新:无法更改第一条记录的复合键值之一

如何将结果集限制为仅 JOIN 中的最新实例

主键映射

打开包含多个附件的电子邮件,同时将选择器限制为仅电子邮件应用程序?