【问题标题】:MySQL Cross Table ConstraintMySQL 跨表约束
【发布时间】:2012-08-06 06:13:30
【问题描述】:

我有三个表,表 A 有一个自动递增的唯一主键,另外两个(表 B 和 C)的主键有一个外键约束,将它们与第一个表的主键联系起来。

我想创建一个约束,以保持第二个和第三个表中的所有行不能包含任何重复项,并且对于表 A 中的所有记录,在 B 或 C 中都有匹配的记录。

所以基本上 A 类型的记录可以是 B 或 C 类型,并且必须是 B 或 C 之一。

在 MySQL 中是否可以在没有触发器的情况下进行此约束?还是需要触发器?

感谢您的帮助。

【问题讨论】:

    标签: mysql triggers constraints


    【解决方案1】:

    您可以使用“类型”表:

    CREATE TABLE Type
      ( type_code CHAR(1) NOT NULL
      , PRIMARY KEY (type_code)
      ) ;
    

    正好有 2 行(与您需要的不同子类型表一样多:

    INSERT INTO Type (type_code)
    VALUES ('B'), ('C') ;
    

    超类型表(包括引用“类型”的列):

    CREATE TABLE A
      ( a_id INT NOT NULL AUTO_INCREMENT
      , type_code CHAR(1) NOT NULL
      , PRIMARY KEY (a_id)
      , UNIQUE KEY (type_code, a_id)
      , FOREIGN KEY (type_code)
          REFERENCES Type (type_code)
      ) ;
    

    子类型表(现在引用 A 的主键和 type_code 的组合:

    CREATE TABLE B
      ( a_id INT NOT NULL
      , type_code CHAR(1) NOT NULL DEFAULT 'B'
      , PRIMARY KEY (type_code, a_id)
      , FOREIGN KEY (type_code, a_id)
          REFERENCES A (type_code, a_id)
      , CHECK (type_code = 'B')
      ) ;
    
    CREATE TABLE C
      ( a_id INT NOT NULL
      , type_code CHAR(1) NOT NULL DEFAULT 'C'
      , PRIMARY KEY (type_code, a_id)
      , FOREIGN KEY (type_code, a_id)
          REFERENCES A (type_code, a_id)
      , CHECK (type_code = 'C')
      ) ;
    

    如果只有 MySQL 实现了CHECK 约束,上述内容将可以正常工作。但事实并非如此。因此,要绝对确保您的所有规范都得到执行,而不是将 'B' 类型数据插入到 C 表中,您必须再添加 2 个“类型”表(并删除 MySQL CHECK 中无用的表)约束):

    CREATE TABLE TypeB
      ( type_code CHAR(1) NOT NULL
      , PRIMARY KEY (type_code)
      ) ;
    
    CREATE TABLE TypeC
      ( type_code CHAR(1) NOT NULL
      , PRIMARY KEY (type_code)
      ) ;
    

    每行恰好有 1 行:

    INSERT INTO TypeB (type_code)
    VALUES ('B') ;
    
    INSERT INTO TypeC (type_code)
    VALUES ('C') ;
    

    以及额外的 FK:

    ALTER TABLE B
      ADD FOREIGN KEY (type_code)
        REFERENCES TypeB (type_code) ;
    
    ALTER TABLE C
      ADD FOREIGN KEY (type_code)
        REFERENCES TypeC (type_code) ;
    

    使用这些约束,表 A 的每一行都将属于 B 或 C 类型,并且将位于相应的表(B 或 C)中,而不会同时存在于两者中。

    如果您还想确保它们恰好在一个表中(并且从不在 B 或 C 中),则在插入 A 时应注意这一点(所有插入都应通过强制执行该要求的事务完成) .

    【讨论】:

    • 非常感谢。我最终使用了触发器,因为我不希望表 A 必须知道表 B 和 C。此外,我的过程也使用事务来确保这些约束。
    猜你喜欢
    • 2015-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-08
    • 1970-01-01
    • 1970-01-01
    • 2021-07-06
    相关资源
    最近更新 更多