我有一个中等大小的 MySQL 数据库,其中包含一个主要的“人员”表,其中包含连接到剧院和戏剧学校的每个人的基本联系信息,我负责维护和开发许多 Web 应用程序。
有些人只是联系人——也就是说,他们的“persons”表记录是我们需要存储的关于他们的所有信息。许多其他人虽然必须能够为各种系统承担不同的角色。其中,大多数都是从学生开始的。有些人从员工开始。学生可以成为实习生或表演者;员工可以成为学生;所有教师都是雇员和表演者等。
从本质上讲,它们是任何个人可能必须佩戴的各种不同的“帽子”,以便访问系统的不同部分并与之交互,以及在我们网站的公共页面上提供有关它们的信息。
我对实现这个模型的选择是有几个其他的表来代表这些“帽子”——这些表包含补充基本“人”信息的元信息,所有这些都使用“人”ID作为他们的主键。例如,作为教师的人在教师表中有一条记录,其中包含他或她的简短传记信息和工资率。所有教师也是员工(但并非所有员工都是教师),这意味着他们在员工表中有一个记录,允许他们将工作时间提交到我们的工资系统中。
我的问题是,这样实现模型有什么缺点?我能想到的唯一另一个选择是用对于大多数条目来说是空的和无用的字段来填充persons表,然后有一个人可以属于的繁琐的“组”表,然后几乎每个表都有每个系统有一个 personperson_id
外键,然后依赖业务逻辑来验证所引用的 person_id 是否属于适当的组;但这很愚蠢,不是吗?
下面是一些示例表声明,希望它们可以展示我当前如何将所有这些放在一起,并希望说明为什么我认为这是一种更明智的方式来模拟系统必须处理的各种情况的现实。
欢迎任何和所有的建议和意见。我很感激你的时间。
编辑一些受访者提到使用 ACL 来保证安全性——我在最初的问题中没有提到我实际上是在使用单独的 ACL 包来为不同系统的实际用户进行细粒度的访问控制。我的问题更多是关于在数据库模式中存储有关人员的元数据的最佳实践。
CREATE TABLE persons (
`id` int(11) NOT NULL auto_increment,
`firstName` varchar(50) NOT NULL,
`middleName` varchar(50) NOT NULL default '',
`lastName` varchar(75) NOT NULL,
`email` varchar(100) NOT NULL default '',
`address` varchar(255) NOT NULL default '',
`address2` varchar(255) NOT NULL default '',
`city` varchar(75) NOT NULL default '',
`state` varchar(75) NOT NULL default '',
`zip` varchar(10) NOT NULL default '',
`country` varchar(75) NOT NULL default '',
`phone` varchar(30) NOT NULL default '',
`phone2` varchar(30) NOT NULL default '',
`notes` text NOT NULL default '',
`birthdate` date NOT NULL default '0000-00-00',
`created` datetime NOT NULL default '0000-00-00 00:00',
`updated` timestamp NOT NULL,
PRIMARY KEY (`id`),
KEY `lastName` (`lastName`),
KEY `email` (`email`)
) ENGINE=InnoDB;
CREATE TABLE teachers (
`person_id` int(11) NOT NULL,
`bio` text NOT NULL default '',
`image` varchar(150) NOT NULL default '',
`payRate` float(5,2) NOT NULL,
`active` boolean NOT NULL default 0,
PRIMARY KEY (`person_id`),
FOREIGN KEY(`person_id`) REFERENCES `persons` (`id`)
ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB;
CREATE TABLE classes (
`id` int(11) NOT NULL auto_increment,
`teacher_id` int(11) default NULL,
`classstatus_id` int(11) NOT NULL default 0,
`description` text NOT NULL default '',
`capacity` tinyint NOT NULL,
PRIMARY KEY(`id`),
FOREIGN KEY(`teacher_id`) REFERENCES `teachers` (`id`)
ON DELETE RESTRICT ON UPDATE CASCADE,
FOREIGN KEY(`classstatus_id`) REFERENCES `classstatuses` (`id`)
ON DELETE RESTRICT ON UPDATE CASCADE,
KEY (`teacher_id`,`level_id`),
KEY (`teacher_id`,`classstatus_id`)
) ENGINE=InnoDB;
CREATE TABLE students (
`person_id` int(11) NOT NULL,
`image` varchar(150) NOT NULL default '',
`note` varchar(255) NOT NULL default '',
PRIMARY KEY (`person_id`),
FOREIGN KEY(`person_id`) REFERENCES `persons` (`id`)
ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB;
CREATE TABLE enrollment (
`id` int(11) NOT NULL auto_increment,
`class_id` int(11) NOT NULL,
`student_id` int(11) NOT NULL,
`enrollmenttype_id` int(11) NOT NULL,
`created` datetime NOT NULL default '0000-00-00 00:00',
`modified` timestamp NOT NULL,
PRIMARY KEY(`id`),
FOREIGN KEY(`class_id`) REFERENCES `classes` (`id`)
ON DELETE RESTRICT ON UPDATE CASCADE,
FOREIGN KEY(`student_id`) REFERENCES `students` (`id`)
ON DELETE RESTRICT ON UPDATE CASCADE,
FOREIGN KEY(`enrollmenttype_id`) REFERENCES `enrollmenttypes` (`id`)
ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB;