【问题标题】:postgresql: foreign key to either tableA or tableBpostgresql:表A或表B的外键
【发布时间】:2011-01-31 09:12:33
【问题描述】:

我正在尝试弄清楚如何使用 Postgresql 8 定义数据库的架构。

我有 2 张桌子:

Journals, Books

定义我拥有的出版物

Journal:
id_j, name, issn, other fields

Book:
id_b, name, isbn, author, other fields

我还有另一个表 Scans,它在逻辑上引用了前面的两个表。

Scans:
id, medium, source, status

每个Journal 或Book 可以有多个Scan,但每个Scan 只能引用一个Journal 或Book。

为了形式化,我的第一个想法是在Scans 中放入两个外键

Scans:
id, medium, source, status, id_j, id_b

并填写id_j或id_b

但这个解决方案在我看来有点奇怪。

我不想(如果可能的话)以这样的方式定义表格:

Scans:
id, medium, source, status, id_other_table, other_table_name

因为我想在表格之间建立正式的联系。

有什么想法吗?

【问题讨论】:

    标签: sql database database-design postgresql


    【解决方案1】:

    要考虑的替代方法是在表中显式具有 2 个可为空的外键列,以及其中一个(并且只有一个)不应为空的约束:

    CREATE TABLE scan (id INT NOT NULL, journal_id int, book_id int,
           PRIMARY KEY (id),
           FOREIGN KEY (journal_id) REFERENCES journal (id),
           FOREIGN KEY (book_id) REFERENCES book (id),
           CONSTRAINT check_single_source CHECK (num_nonnulls(book_id,journal_id) = 1)
    );
    

    【讨论】:

      【解决方案2】:
      CREATE TABLE source (
             type CHAR(1) NOT NULL CHECK (type IN ('J', 'B')),
             id INT NOT NULL,
             PRIMARY KEY (type, id)
      );
      
      CREATE TABLE book (
             type CHAR(1) NOT NULL CHECK(type = 'B'), id INT NOT NULL,
             PRIMARY KEY (id),
             FOREIGN KEY (type, id) REFERENCES source (type, id) ON DELETE CASCADE
      );
      
      CREATE TABLE journal (
             type CHAR(1) NOT NULL CHECK(type = 'J'), id INT NOT NULL,
             PRIMARY KEY (id),
             FOREIGN KEY (type, id) REFERENCES source (type, id) ON DELETE CASCADE
      );
      
      CREATE TABLE scan (id INT NOT NULL, sourcetype CHAR(1) NOT NULL, sourceid INT NOT NULL,
             PRIMARY KEY (id),
             FOREIGN KEY (sourcetype, sourceid) REFERENCES source (type, id)
      );
      

      使用这种设计,您不应该直接从book 或journal 中删除记录:而是从表source 中删除,这会将操作级联到相应的表。

      您可以将book 和journal 共有的属性移动到source。

      【讨论】:

      • 是的,标准化通常会有所帮助。在规范化之后对数据库进行非规范化,而不是之前。
      猜你喜欢
      • 1970-01-01
      • 2011-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多