让我们说有三个表叫老师,学生和消息。
教师:
-----------
ID | name |
-----------
t_1| Dani |
-----------
t_2| Billy|
-----------
生:
-------------
ID | name |
-------------
s_1| Luckas |
-------------
s_2| Oliver |
-------------
消息:
--------------------------------
| ID | sender_ID | receiver_ID |
--------------------------------
| 1 | s_1 | s_2 |
--------------------------------
| 2 | s_1 | t_1 |
--------------------------------
| 3 | s_1 | t_2 |
--------------------------------
| 4 | t_1 | s_2 |
--------------------------------
对不起表格看起来我不知道如何做得更好。
我希望只允许教师或学生的值存储在messages.sender_id和messages.receiver_Id中,就像FK一样。
我需要知道是否可能,如果可能,怎么样?
答案 0 :(得分:1)
您有两种不同的选择。 首先是创建一个Person表,另一个是PersonType。 PersonType将包含"学生"和#34;老师"作为价值观。将PersonTypeId添加到Person并为PersonType创建外键,这将作为学生和教师之间的鉴别器。将外键添加到Person的Messages表中。
第二个是创建"数据库继承"。使用学生和教师之间的公共数据创建Person表。然后,使用每个的特定数据创建“学生和教师”表,并在两者上添加外键。将您的外键添加到来自Person表的消息。 第一种解决方案更具性能。
答案 1 :(得分:0)
MySQL不支持声明性外键约束来强制执行此完整性规则。使用所示的表(即不更改表),我们可以使用触发器来强制执行这些类型的参照完整性规则。它需要在所有三个表上组合BEFORE INSERT,BEFORE UPDATE,BEFORE DELETE触发器。
我们没有看到任何会阻止相同值(例如k_9
)出现student
和teacher
表格的规则。因此,sender_ID
的邮件中的一行是k_9
,我们无法确定引用的内容,student
,teacher
或两者。
如果可以更改表定义,我们可以将person
表实现为student
和teacher
的超类。实现这一点的几种模式。一种可能性是添加鉴别器列。
person
ID type name
--- ------- ------
s_1 student Lukas
s_2 student Oliver
t_1 teacher Dani
t_2 teacher Billy
k_9 student Rover
使用该表,从messages
声明外键约束将是直截了当的。
我们可以在原始设计中返回students
表和teachers
表的等价物:
生
SELECT ID, name FROM person WHERE type = 'student'
教师
SELECT ID, name FROM person WHERE type = 'teacher'
但是只给出问题中显示的三个表,就不可能声明外键约束来强制执行指定的引用完整性规则。执行这些完整性规则的唯一方法是通过触发器。
BEFORE INSERT ON messages
FOR EACH ROW
BEGIN
-- if NEW.sender_ID is non-NULL, verify the value appears
-- as value in `ID` column of either `students` or `teachers`
-- if not, throw an error
-- if NEW.receiver_ID is non-NULL, verify the value appears
-- as value in `ID` column of `students` or `teachers`
-- if not, throw an error
END
我们还需要UPDATE ON消息的触发器,以及UPDATE和DELETE ON学生和教师