映射ER图的专业化,在插入子表时重复

时间:2017-03-06 17:06:13

标签: php mysql database entity-relationship

我有一个用户表,他可以是教师或校长My ER diagram 。我认为这种脱节专业化在ER中是合适的。我使用MySQL dbms,在创建表后,我在User表中创建了一个用户(例如UserId = 31)。但问题是,当我使用UserId = 31将新记录插入教师表并在校长表中插入相同的UserId时,它不会给出任何错误。我认为这被认为违反了不相关的财产。

我有一个具有此属性的用户表

用户(UserId,用户名,密码,性别,姓名,地址,教育,大学,手机)。

和像这样的映射后的教师表

老师(用户ID,疗程)。

和校长表。 校长(用户ID,Years_Of_Service)。

当我创建了老师和校长表时,我创建了它们而没有主键,然后我在每个表中添加了UserId属性的索引,并在User表中引用了UserId。

我的问题:如何使用MySQL实现表格的不相交?

提前致谢

1 个答案:

答案 0 :(得分:0)

这样做的一种方法是为每个表添加类型指示符,以及包含类型指示符的FK约束。

我只是要显示超类型以及一个子类型表。

CREATE TABLE `User` (
  `UserID` bigint(21) NOT NULL,
  `UserType` enum('H', 'T') NOT NULL,
  ...
  PRIMARY KEY (`UserID`),
  UNIQUE KEY (`UserID`,`UserType`)
) ENGINE=InnoDB;

CREATE TABLE `Teacher` (
  `UserID` bigint(21) NOT NULL,
  `UserType` enum('H', 'T') NOT NULL,
  ...
  PRIMARY KEY (`UserID`),
  FOREIGN KEY (`UserID`, `UserType`) REFERENCES `User` (`UserID`, `UserType`) ON UPDATE CASCADE
) ENGINE=InnoDB;

请注意,必须在超类型和子类型表中以相同的方式定义UserType列才能创建FK约束。我在User表中添加了一个唯一键,以支持子类型中的复合FK约束。要限制每个子类型表中的类型指示器,我们然后创建触发器:

DELIMITER ;;

CREATE TRIGGER check_teacher_insert BEFORE INSERT ON Teacher
    FOR EACH ROW
    BEGIN
        IF new.UserType != 'T' THEN
            SIGNAL SQLSTATE '45000'   
            SET MESSAGE_TEXT = 'Invalid UserType in Teacher';
        END IF;
    END;
;;

CREATE TRIGGER check_teacher_update BEFORE UPDATE ON Teacher
    FOR EACH ROW
    BEGIN
        IF new.UserType != 'T' THEN
            SIGNAL SQLSTATE '45000'   
            SET MESSAGE_TEXT = 'Invalid UserType in Teacher';
        END IF;
    END;
;;

DELIMITER ;

另一种方法是省略类型指标,只使用触发器:

DELIMITER ;;

CREATE TRIGGER check_teacher_insert BEFORE INSERT ON Teacher
    FOR EACH ROW
    BEGIN
        IF EXISTS (
            SELECT 1
            FROM Headmaster
            WHERE UserID = new.UserID
        ) THEN
            SIGNAL SQLSTATE '45000'   
            SET MESSAGE_TEXT = 'Invalid UserID in Teacher - already exists in HeadMaster';
        END IF;
    END;
;;

CREATE TRIGGER check_teacher_update BEFORE UPDATE ON Teacher
    FOR EACH ROW
    BEGIN
        IF EXISTS (
            SELECT 1
            FROM Headmaster
            WHERE UserID = new.UserID
        ) THEN
            SIGNAL SQLSTATE '45000'   
            SET MESSAGE_TEXT = 'Invalid UserID in Teacher - already exists in HeadMaster';
        END IF;
    END;
;;

DELIMITER ;