MySQL 外键 - 如何跨表强制执行一对一?

标签 mysql

如果我在 MySQL 中有一个表代表一个基类,我有一堆表代表派生类中的字段,每个表都使用外键引用回基表,有什么办法让 MySQL 在派生表和基表之间强制执行一对一关系,还是必须在代码中完成?

以下面的 quick 'n' dirty schema 为例,有没有办法让 MySQL 确保 product_cd 和 product_dvd 中的行不能共享相同的 product_id?是否有更好的方法来设计架构以允许数据库强制执行此关系,或者根本不可能?

CREATE TABLE IF NOT EXISTS `product` (
    `product_id` int(10) unsigned NOT NULL auto_increment,
    `product_name` varchar(50) NOT NULL,
    `description` text NOT NULL,
    PRIMARY KEY  (`product_id`)
) ENGINE = InnoDB;

CREATE TABLE `product_cd` (
    `product_cd_id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
    `product_id` INT UNSIGNED NOT NULL ,
    `artist_name` VARCHAR( 50 ) NOT NULL ,
    PRIMARY KEY ( `product_cd_id` ) ,
    INDEX ( `product_id` )
) ENGINE = InnoDB;

ALTER TABLE `product_cd` ADD FOREIGN KEY ( `product_id` ) 
    REFERENCES `product` (`product_id`) 
    ON DELETE RESTRICT ON UPDATE RESTRICT ;

CREATE TABLE `product_dvd` (
    `product_dvd_id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
    `product_id` INT UNSIGNED NOT NULL ,
    `director` VARCHAR( 50 ) NOT NULL ,
    PRIMARY KEY ( `product_dvd_id` ) ,
    INDEX ( `product_id` )
) ENGINE = InnoDB;

ALTER TABLE `product_dvd` ADD FOREIGN KEY ( `product_id` ) 
    REFERENCES `product` (`product_id`) 
    ON DELETE RESTRICT ON UPDATE RESTRICT ;

@ Skliwz ,您能否提供更多有关如何使用触发器通过提供的架构强制执行此约束的详细信息?

@ boes , 听起来不错。在您有 child 的 child 的情况下,它如何运作?例如,如果我们添加 product_movie 并使 product_dvd 成为 product_movie 的子项?让 product_dvd 的检查约束也必须考虑所有子类型是否会成为可维护性噩梦?

最佳答案

可以通过在外键的列上定义唯一约束来实现 1:0-1 或 1:1 关系,因此只能存在一种组合。通常这将是子表的主键。

如果外键位于引用表的主键或唯一键上,它将把它们限制为父表中存在的值,并且列上的唯一约束将它们限制为唯一性。这意味着子表在受约束的列中只能具有与父表对应的值,并且每行必须具有唯一值。这样做会强制子表最多有一行对应于父记录。

关于MySQL 外键 - 如何跨表强制执行一对一?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/113803/

相关文章:

php - 如何使用 php 将两个不同的复选框值插入到一个 mysql 表的不同列中?

php - MySQL:获取具有连续日期的行

PHP 页面无法正确显示

php - 使用 PHP printf 生成 sql 查询

mysql - LEFT JOIN 表和右边不存在的空值

php - 如何使用 php 用逗号分隔 mysql 行值?

java - JDBC INSERT INTO - 错误的主键

mysql - 两个值之间的 SQL 标准

php - 通过php的Mysql CREATEUSER命令

mysql - 在mysql中将日期转换为UTC时间戳