【问题标题】:How do I define the main/primary record of a one-to-many relationship?如何定义一对多关系的主要/主要记录?
【发布时间】:2023-02-14 01:18:37
【问题描述】:

我正在使用 account 表和 profile 表提供服务。一个帐户可以拥有多个配置文件,但帐户始终有一个主要配置文件。这最初是在注册时与帐户一起创建的第一个配置文件,但用户可以添加配置文件并稍后将其设置为主要配置文件。

我尝试了以下设置:

create table account (
    id                   uuid          primary key,
    email                text          unique,
    phone                text          unique,
    created_at           timestamptz,
    primary_profile_id   uuid          references profile on delete restrict,
);

create table profile (
    id           uuid          primary key,
    account_id   uuid          references account on delete cascade,
    username     text          unique,
    about        text,
    created_at   timestamptz
);

这不起作用,因为:

  • 您甚至不能运行它来创建表,因为它们都依赖于另一个预先存在的表。解决方法是创建不带 primary_profile_id 的帐户表,并在创建 profile 表后更改表以添加该列,但是......
  • 即使您可以创建表,也不能向其中添加记录,因为您需要先存在另一个表才能引用它。如果您将 primary_profile_id 保留为 NULL 并在创建配置文件后对其进行更改,这在技术上是可行的,但这些列不应该可以为空,因此这并不是很理想。

这个有什么好的解决办法吗?我还考虑过在配置文件表上有一个 primary 布尔值,但是数据库端没有任何东西阻止单个帐户下的多个配置文件为真。

谢谢你的帮助 :)

【问题讨论】:

  • 创建两个没有 fk 列的表,做 alter tables 添加列和 fk 约束并允许这些约束为空。
  • 在插入后需要更新并创建第三个表来绑定这两个关系将是更好的选择 imo。
  • 数据库方面没有任何东西可以阻止多个配置文件的情况.是的,有一个Partial Unique Index。它将允许您仅在 primary 为真时创建索引。
  • @mwalter 不,它不需要第三张桌子。多对多需要第三张表。不适用于所描述的一对多。

标签: postgresql


【解决方案1】:

您使用外键强制执行您的要求的想法很好。

创建表没问题;你可以简单地运行

create table account (
    id                   uuid          primary key,
    email                text          unique,
    phone                text          unique,
    created_at           timestamptz,
    primary_profile_id   uuid,
);

create table profile (
    id           uuid          primary key,
    account_id   uuid          references account on delete cascade,
    username     text          unique,
    about        text,
    created_at   timestamptz
);

ALTER TABLE account
   ADD FOREIGN KEY (primary_profile_id) REFERENCES profile
      DEFERRABLE INITIALLY DEFERRED;

像这样的延迟外键约束不会在插入行时检查,而是在事务结束时检查。所以你可以先添加account,然后再添加匹配的profile,只要你在同一个事务中插入两者。

我建议尽可能在您的列定义中使用 NOT NULL

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-26
    • 1970-01-01
    相关资源
    最近更新 更多