【问题标题】:Solving a circular foreign key relationship with PostgreSQL用 PostgreSQL 解决循环外键关系
【发布时间】:2021-05-30 00:43:26
【问题描述】:

我有一个具有以下数据结构的数据库:

USER 表:

Id  Name    
1   Alice
2   Bob
3   Charlie

文件夹表:

Id  Name       User
1   Invoices   2
2   Contracts  3
3   Receipts   3

文档表:

Id  Name                  User    Folder
1   Birth Certificate     1       null
2   Fax Machine Receipt   3       3
3   Work NDA              3       2
4   Laptop Invoice        2       1
5   Job Application       2       null

这是我将其概念化的架构:

这里的想法是用户拥有文档和文件夹,这些文档可以可选地分类到文件夹中。我需要一个约束来确保文档仅被分类到拥有该文档的同一用户拥有的文件夹中(即 DOCUMENT(user) = FOLDER(user)),或者一种巧妙的方式来规范化模式以防止出现哪个文档的用户与文件夹的用户不匹配。

【问题讨论】:

  • 什么循环? PS 为什么你认为这涉及到数据库规范化? (“规范化”并不意味着“重新排列”或“约束”或“设计良好”。) PS 这是一个常见问题解答。在考虑发布之前,请阅读手册和谷歌任何错误消息以及您的问题/问题/目标的许多清晰、简洁和精确的措辞,带有和不带有您的特定名称/字符串/数字、“site:stackoverflow.com”和标签;阅读许多答案。如果您发布问题,请使用一个短语作为标题。反映你的研究。 How to Ask

标签: postgresql database-design foreign-keys relational-database database-normalization


【解决方案1】:

您可以将("user", "folder") 设为"folder" 中的一个键,并在"document" 中引用它。

CREATE TABLE "user"
             ("id" serial,
              PRIMARY KEY ("id"));

CREATE TABLE "folder"
             ("id" serial,
              "user" integer
                     NOT NULL,
              PRIMARY KEY ("id"),
              UNIQUE ("id",
                      "user"),
              FOREIGN KEY ("user")
                          REFERENCES "user"
                                     ("id"));

CREATE TABLE "document"
             ("id" serial,
              "user" integer
                     NOT NULL,
              "folder" integer,
              PRIMARY KEY ("id"),
              FOREIGN KEY ("user")
                          REFERENCES "user"
                                     ("id"),
              FOREIGN KEY ("folder",
                           "user")
                          REFERENCES "folder"
                                     ("id",
                                      "user"));

另一种选择是始终为每个用户提供一个默认文件夹,然后通过引用 "folder" 来处理所有内容。

【讨论】:

  • 我没有意识到外键可以像这样引用多个列。谢谢!我会在上午测试一下
  • @Ataraxia:形式上,一个 [(primary|foreign)] 键实际上总是一个 tuple 列。但是当它是一个单元组并且因为人类往往很懒惰时,这被简化了,我们只是说列(单元组中的一列)是一个 [(primary|foreign)] 键。
  • 所以,Postgres 告诉我 FOLDER 上的“用户”列必须是唯一的,这是我们不希望的,因为我希望用户能够拥有多个文件夹。
  • a UNIQUE constraint does not exist on referenced columns: FOLDER in statement [ALTER TABLE PUBLIC.Document ADD CONSTRAINT fk_document_folder_user FOREIGN KEY (folder, "USER") REFERENCES PUBLIC.Folder (uuid, "USER")]
  • @Ataraxia:您似乎没有正确应用 "folder" 的唯一约束。确保 ("id", "user") 两列的元组声明为唯一的,而不仅仅是单列。
猜你喜欢
  • 2019-09-03
  • 2016-07-26
  • 2018-09-09
  • 2013-08-23
  • 2018-10-13
  • 1970-01-01
  • 1970-01-01
  • 2014-01-28
  • 2021-04-26
相关资源
最近更新 更多