代码之家  ›  专栏  ›  技术社区  ›  Matt Sheppard

对两列主键的外键引用

  •  5
  • Matt Sheppard  · 技术社区  · 14 年前

    我正在建立一个数据库,它必须在mysql、postgresql和sqlite上工作。我的一个表有两列主键:

    CREATE TABLE tournament (
        state CHAR(2) NOT NULL, 
        year INT NOT NULL,
        etc..., 
        PRIMARY KEY(state, year)
    );
    

    我想参考一下 tournament 另一张桌子的桌子,但是 我希望这个参考是 可空的 . 我可以这样做,想象一个胜利者不一定有一场比赛:

    CREATE TABLE winner (
        name VARCHAR NOT NULL,
        state CHAR(2) NULL,
        year INT NULL
    );
    

    如果 state 是空的 year 不是,反之亦然,表将不一致。我相信以下几点 FOREIGN KEY 约束修复它:

    ALTER TABLE winner ADD CONSTRAINT FOREIGN KEY fk (name, state) REFERENCES tournament (name, state);
    

    这是强制一致性的正确方法吗?此架构是否正确规范化?

    1 回复  |  直到 14 年前
        1
  •  4
  •   Evan Carroll    14 年前

    规则1:总是说你正在使用的数据库

    好吧,我建议你看看 ON DELETE 子句和 MATCH 条款。因为pg是相当符合SQL的,所以我将向您指出 CREATE TABLE .

    Excerpt:

    这些子句指定了一个外键 约束,它要求 一个或多个列的组 新表只能包含值 与引用的 某行的列 引用的表。如果改写为 省略,的主键 使用reftable。被引用的 列必须是 中的唯一或主键约束 引用的表。注意 外键约束不能 在临时表和之间定义 永久性桌子。

    插入到引用中的值 列与 引用表的值和 使用给定的 匹配类型。有三场比赛 类型:完全匹配、部分匹配和 简单匹配,这也是 违约。完全匹配不允许 多列外键的列 除非所有外键列都为空 是空的。简单匹配允许 同时外键列为空 外键的其他部分不是 无效的。部分匹配尚未完成 实施。

    此外,当数据在 引用的列已更改,确定 对中的数据执行操作 此表的列。关于删除 子句指定要执行的操作 当引用行位于 正在删除引用的表。 同样,ON UPDATE子句 指定当 引用的列中的引用列 正在将表更新为新值。 如果行已更新,但 引用的列实际上不是 已更改,未执行任何操作。 除“否”以外的参照动作 动作检查不能延迟,甚至 如果声明约束 可延期的下面是 每个条款的可能操作:

    此外,MS SQL还有一个主要的例外——它不允许外键中的部分匹配(匹配简单和匹配部分)行为(默认和强制匹配完全)。有一些解决方法,您可以在表的某部分创建一个匹配的完整索引,该索引对于组合键的任何组成部分都不为空。