在多个其他 table 中包含一个 table 的值并允许 FK 引用

Include one table's values in multiple other tables and allow FK references

在设计 SQL 数据库方面,我仍然是一个相对的新手,如果这是我遗漏的明显问题,我深表歉意。

我有一些 tables 的受控词汇表用于某些值,我表示为引用受控词汇表 tables 的 FK(我试图表示的不同词汇表很少).我的模式规范允许这些词汇表中的每一个还允许一组受控的“未知”信息值(来自 DataCite)。下面是一个使用 table dates 的示例,它必须指定 date_type,它应该是 date_typesunknown_values 中的值。我还有一些关于这个模型的 tables,每个都有自己特定的受控词汇表,但也应该允许来自 unknown_values 的值。因此 unknown_values 中的值应该在许多 table 具有与 date_types.

相似结构的受控词汇表中共享
CREATE TABLE dates ( 
    date_id              integer NOT NULL  PRIMARY KEY autoincrement ,
    date_value           date NOT NULL DEFAULT CURRENT_DATE   ,
    date_type            text NOT NULL    ,
    FOREIGN KEY ( date_type ) REFERENCES date_types( date_type )  
 );

CREATE TABLE date_types ( 
    date_type            text NOT NULL  PRIMARY KEY  ,
    definition           text     
 );

CREATE TABLE unknown_values ( 
    code                 text NOT NULL  PRIMARY KEY  ,
    definition           text     
 );

INSERT INTO date_types (date_type, definition)
VALUES
    ('type_a', 'The first date type'),
    ('type_b', 'The second date type');

INSERT INTO unknown_values (code, definition)
VALUES
    (':unac', 'Temporarily inaccessible'),
    (':unal', 'Unallowed, suppressed intentionally'),
    (':unap', 'Not applicable, makes no sense'),
    (':unas', 'Value unassigned (e.g., Untitled)'),
    (':unav', 'Value unavailable, possibly unknown'),
    (':unkn', 'Known to be unknown (e.g., Anonymous, Inconnue)'),
    (':none', 'Never had a value, never will'),
    (':null', 'Explicitly and meaningfully empty'),
    (':tba', 'To be assigned or announced later'),
    (':etal', 'Too numerous to list (et alia)');

我的第一个想法是创建 date_typesunknown_values 的并集的视图,但是您不能对视图进行 FK 引用,所以这不是 suitable。

“最简单”的解决方案是在每个受控词汇表 table(date_types 等)中复制来自 unknown_values 的值,但感觉有重复值是不正确的。

我还考虑了一个 table 用于所有具有第三个字段的受控词汇表(类似于 vocabulary_category,值类似于 'date'),所以我所有的 tables 可以引用那个 table,但是我可能需要一个函数和一个 CHECK 约束来确保该值具有正确的“类别”。这感觉不雅和凌乱。

我对继续进行的最佳方式或搜索内容以寻求帮助感到困惑。我无法想象这种要求太罕见了,但我似乎无法在网上找到任何解决方案。我的目标数据库是 SQLite,但我也对 PostgreSQL 中可能的解决方案感兴趣。

您要求的是 FK 具有可选引用的能力 table。还发现 Postgres 和 SQLite(?) 都提供了这个选项(afaik 也没有任何其他 RDBMS)。 Postgres at lease 提供了一个解决方法,我不知道它在 SQLite 中是否可行。您需要:

  • 删除当前定义的 FK 的非空约束
  • 添加引用 unknown_values table
  • 的 FK 列
  • 添加 check 约束,在列上恰好需要 1 date_type 并且新 FK 列为空。请参阅 num_nulls 函数。

您需要的更改:(参见 demo

alter table dates 
      alter column date_type 
            drop not null; 
           
alter table dates 
      add  unknown_value text 
           references unknown_values(code); 
          
alter table dates 
      add constraint  one_null 
          check (num_nulls(date_type, unknown_value ) = 1);

注意:Postgres 不支持 autoincrement 关键字。使用生成的列 generated always as identity(对于旧版本使用 serial)也是如此。