【问题标题】:SQL - Create Foreign Key on multiple columns with different count of columnsSQL - 在具有不同列数的多列上创建外键
【发布时间】:2016-09-05 20:26:39
【问题描述】:

我试图在一个表的一列上创建一个外键以指向另一个表的两列,但我似乎遇到了错误。

这可能吗:

ALTER TABLE table_a add CONSTRAINT table_a_table_b FOREIGN KEY
(table_a.id,false) REFERENCES table_b(table_b.id,some_boolean);

不应允许 table_a 引用 table_b 中 'some_boolean' 为 true 的实体。

【问题讨论】:

    标签: sql postgresql foreign-keys


    【解决方案1】:

    一种方法是将虚拟列 some_bool 添加到 table_a,默认值为 false,然后让您的 FK 约束引用这两列:

    create table table_a ( id varchar, some_bool bool default false);
    create table table_b ( id varchar, some_bool bool);
    
    alter table table_b add constraint table_b_unique unique( id, some_bool);
    ALTER TABLE table_a add CONSTRAINT table_a_table_b 
    FOREIGN KEY (id,some_bool) 
    REFERENCES table_b(id,some_bool);
    

    【讨论】:

    • table_b 经常使用,所以我必须将“some_bool”列添加到我想要 table_b 的外键的每个表中。
    • 是的,这不是一个理想的解决方案:(
    【解决方案2】:

    我自己找到了解决方案,但似乎这种方式也不“干净”:

    我在两个表上都创建了两个 CHECK CONSTRAINT。

    CREATE FUNCTION isSomeBooleanSet(BIGINT) RETURNS BOOLEAN AS 
    'select some_boolean from table_b where id = $1'
    LANGUAGE SQL IMMUTABLE
    RETURNS NULL ON NULL INPUT;
    
    ALTER TABLE table_a ADD CONSTRAINT
    some_boolean_true_is_not_allowed CHECK (isSomeBooleanSet(table_b_id)=false);
    
    CREATE OR REPLACE FUNCTION tableAReferenceToInvalidTableBEntity(BIGINT, BOOLEAN) 
    RETURNS BOOLEAN
    AS 'select count(*)>1 from table_a inner join table_b on table_b.id = table_a.table_b_id where table_a.table_b_id = $1 and $2 = true;'
    LANGUAGE SQL IMMUTABLE RETURNS NULL ON NULL INPUT;
    
    ALTER TABLE table_b add CONSTRAINT table_a_cannot_realte_to_table_b_some_boolean_set CHECK (tableAReferenceToInvalidTableBEntity(id,some_boolean)=false);
    

    【讨论】:

    • 不幸的是,这是您能找到的最佳解决方案。您在这里本质上想要的是从table_atable_b子集 的外键,Postgres 没有简明的方式来支持它。这是我多次想要的功能,但可惜没有这样的运气。像这样的触发器和函数很难看,但如果你需要这个约束,这是最好的。
    猜你喜欢
    • 2021-11-23
    • 2021-10-24
    • 2018-12-16
    • 1970-01-01
    • 1970-01-01
    • 2013-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多