当数据库遇上外键
现在在一个数据库中,用以下命令建两张表(课程性质和grade表)
关系如下图所示:(grade中的课程性质是课程性质表的外键)
建表语句如下:
DROP TABLE IF EXISTS `课程性质`;
CREATE TABLE `课程性质` (
`id` int(11) NOT NULL,
`课程性质` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `课程性质` (`课程性质`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `grade`;
CREATE TABLE `grade` (
`课程代码` varchar(6) NOT NULL,
`课程名称` varchar(50) DEFAULT NULL,
`课程性质` varchar(30) DEFAULT NULL,
`期末成绩` double DEFAULT NULL,
`总评成绩` double DEFAULT NULL,
`课程学分` double DEFAULT NULL,
PRIMARY KEY (`课程代码`),
KEY `课程性质` (`课程性质`),
CONSTRAINT `grade_ibfk_1` FOREIGN KEY (`课程性质`) REFERENCES `课程性质` (`课程性质`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
当你想在grade表中插入以下的记录的时候:运行如下语句
(语句一)
INSERT INTO `grade` VALUES ('000042', '大学语文', '通识教育必修课', '78', '78', '2');
这时你可能发现插入不了,发现你有外键依赖不能插入该记录
所以你先执行如下:运行如下语句
(语句二)
INSERT INTO `课程性质` VALUES ('1', '通识教育必修课');
这时你可能以为这次再次运行(语句一)
INSERT INTO `grade` VALUES ('000042', '大学语文', '通识教育必修课', '78', '78', '2');
没问题了吧?
你发现还是错了!!!(不要担心,这还是可恶的外键搞得鬼)
最后你会百度得到以下解决方案
原来要改成如下语句才可实现你所想要达成的效果
(语句三)
INSERT INTO `grade` VALUES ('000042', '大学语文',(select `课程性质` from `课程性质` where `课程性质`='通识教育必修课'), '78', '78', '2');
这下你会发现真的可以了。
但是有时候你会发现有时并不需要这么麻烦,而且这样为了插入一条数据还得提前查询一次,肯定影响了数据库的性能
有时候你会很庆幸你不用这么做,有的时候你还非得这么做
那怎么办呢?
可以将其写成存储过程,从而提高一点其执行速率。(推荐使用存储过程)
综上所述,建立外键是个可以建立数据库中列与列的限制关系,但是无疑会增加服务器资源的消耗,编写sql语句的复杂度增加,所以在大型的数据库中能少用则少用。