2013-07-01 61 views
1

关系:students (1 can have N) addresses更新同一个表中存储过程更新后和INSERT

场景:学生可以有很多记录,但只有一个相关记录必须有“current”字段设置为“Yes”(等价值是NULL),所以下面的查询应该每个学生总是只返回一条记录。

SELECT * FROM address WHERE student_id = 5 AND current = 'Yes' 

问题: 人们有时标记多个记录为INSERT或UPDATE对同一个学生后“是”,所以我需要避免。在MySQL中使用触发器或存储过程的最佳方式是什么?

如果UPDATE在“地址”表会发生那么这应该某处运行,以纪念其他记录为NULL:UPDATE addresses SET current = NULL WHERE student_id = IN_student_id

如果INSERT发生在“地址”表那么这应该某处运行,以纪念其他记录为NULL:UPDATE addresses SET current = NULL WHERE student_id = IN_student_id AND id <> IN_inserted_id

在此先感谢

回答

3

如果你需要的东西自动数据被修改后更新,正确的做法是一个触发器。注意触发器可能会调用存储过程。

然而,你将无法实现在触发because描述的行为:

存储函数或触发器不能由语句修改已被使用(读或写)的表调用函数或触发器。

事实上,在信息“地址X是当前地址”应该被存储在students表中的列,作为一个外键address表。因此,唯一性是有保证的。

像这样(fiddle with it here):

CREATE TABLE student (
    id INT NOT NULL PRIMARY KEY, 
    current_address INT, 
    name VARCHAR(20) 
); 

CREATE TABLE address (
    id INT NOT NULL PRIMARY KEY, 
    student_id INT NOT NULL, 
    contents VARCHAR(50) NOT NULL, 
    CONSTRAINT student_fk FOREIGN KEY student_fk_idx (student_id) 
    REFERENCES student(id) 
); 

ALTER TABLE student 
    ADD CONSTRAINT curraddr_fk_idx 
    FOREIGN KEY curraddr_fk_idx (id, current_address) 
    REFERENCES address(student_id, id); 

声明本结构允许students插入无 “当前地址”。这是因为两个表中至少有一个必须允许其外键的值为NULL(否则我们无法在任何表中添加单个行)。如果更有意义,则可以使用address.student_id代替NULL,并且允许address成为别人的地址,直到您创建相应的student

+0

将地址表的PK存储为学生表中的当前值是个不错的主意。谢谢 – BentCoder