【问题标题】:PostgreSQL: table referencing only part of a composite primary keyPostgreSQL:表仅引用复合主键的一部分
【发布时间】:2017-09-19 02:39:58
【问题描述】:

我正在使用 Postgres 9.6.2 创建电影和电视节目流媒体服务数据库(用于学校项目)。我遇到以下错误:

引用表“watchedepisodes”的给定键没有唯一约束匹配

只要用户观看了至少一集(显示在 WatchedEpisodes 表中)并允许用户对其进行评分,下面的 TVratings 表就会显示一个电视节目。由于 WatchedEpisodes 具有用户 id、电视节目 id、季节和剧集的复合主键,因此我不会从该表中仅引用 uid 和 tid 的复合键。

CREATE TABLE WatchedEpisodes (
  uid int unique references Users(uid),
  tid int,
  season int,
  episode int,
  FOREIGN KEY(tid, season, episode) REFERENCES Episodes(tid, season, episode),
  PRIMARY KEY (uid, tid, season, episode)
);

CREATE TABLE TVRatings (
  uid int,
  tid int,
  rating int check (rating > 0 and rating < 6),
  FOREIGN KEY(uid, tid) REFERENCES WatchedEpisodes(uid,tid),
  PRIMARY KEY(uid, tid)
);

想知道是否有办法只引用该复合键的一部分。这些只是我的两个表,所以如果需要更多信息,我可以添加更多。

【问题讨论】:

    标签: sql database postgresql unique-constraint composite-primary-key


    【解决方案1】:

    这实际上在规范中,但尚未实施。它叫MATCH PARTIAL

    CREATE TABLE foo (
      a int,
      b int,
      c int,
      PRIMARY KEY (a,b,c)
    );
    CREATE TABLE bar (
      a int,
      b int,
      FOREIGN KEY (a,b) REFERENCES foo (a,b) MATCH PARTIAL
    );
    

    你可以read about it in the docs

    使用给定的匹配类型,将插入引用列的值与被引用表和被引用列的值进行匹配。共有三种匹配类型:MATCH FULL、MATCH PARTIAL 和 MATCH SIMPLE(这是默认设置)。 MATCH FULL 不允许多列外键的一列为空,除非所有外键列都为空;如果它们都为空,则该行不需要在引用的表中具有匹配项。 MATCH SIMPLE 允许任何外键列为空;如果其中任何一个为空,则该行不需要在引用的表中具有匹配项。 MATCH PARTIAL 尚未实现。 (当然,可以将 NOT NULL 约束应用于引用列以防止出现这些情况。)

    我认为目前它被视为反特征,因此不太可能很快落地。

    作为一种解决方法,您可以创建另一个只有 (a,b) 的表

    CREATE TABLE baz (
      a int,
      b int,
      PRIMARY KEY (a,b)
    );
    

    从这里您可以将两个表链接到它...

    CREATE TABLE foo (
      a int,
      b int,
      c int,
      PRIMARY KEY (a,b,c),
      FOREIGN KEY (a,b) REFERENCES baz
    );
    CREATE TABLE bar (
      a int,
      b int,
      FOREIGN KEY (a,b) REFERENCES baz
    );
    

    【讨论】:

    • 如果我不能进行部分匹配,你知道我可以解决这个问题的另一种方法吗?
    • @HannahRiedman 已更新。如果此答案对您有用,请考虑将其标记为已选择并将问题标记为移至Database Administrators 它可能应该在的位置。 ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多