学生信息、成绩、课程数据表,提取码:iqub
评论及回复数据表,提取码:hdr7
整数类型
整数类型说明:
小数类型
浮点数取值范围:
utf8mb3字符集:一个字符=3个字节
utf8mb4字符集:一个字符=4个字节
选择的参考规则
同创建表时创建外键约束
CREATE TEABLE `account_user`( `id` INT NOT NULL AUTO_INCREMENT, PRIMARY KEY(`id`) ); 建立外键的时,可以给外键取一个名字,方便后续进行修改和删除 CREATE TABLE `account_user_address`( `user_id` INT NOT NULL, FOREIGN KEY [key_name](`user_id`) REFERENCES `account_user`(`id`) );
修改表时增加外键约束
ALTER TABLE `account_user_address` ADD FROEIGN KEY key_name(`user_id`) REFERENCES `account_user(`id`)`;
删除外键约束
ALTER TABLE `account_user_address` DROP FOREIGN KEY key_name;
外键约束使用要点
-- 学生信息表 CREATE TABLE `school_student_info` ( `id` INT NOT NULL AUTO_INCREMENT COMMENT '主键ID', `stu_no` SMALLINT NOT NULL COMMENT '学号', `stu_name` VARCHAR(16) NOT NULL COMMENT '姓名', `sex` TINYINT DEFAULT 1 COMMENT '性别, 0: 女,1:男', `age` TINYINT UNSIGNED DEFAULT 0 COMMENT '年龄', `class_name` VARCHAR(10) DEFAULT '' COMMENT '班级', `address` VARCHAR(255) DEFAULT '' COMMENT '家庭住址', `phone_no` CHAR(11) DEFAULT '' COMMENT '联系电话', PRIMARY KEY (`id`) ) COMMENT '学生信息表'; -- 课程信息表 CREATE TABLE `school_course_info` ( `id` INT NOT NULL AUTO_INCREMENT COMMENT '主键ID', `course_name` VARCHAR(64) NOT NULL COMMENT '课程名称', `teacher` VARCHAR(16) NOT NULL COMMENT '老师', `desc` VARCHAR(512) DEFAULT '' COMMENT '课程描述', PRIMARY KEY (`id`) )COMMENT '课程信息表'; -- 学生成绩表 CREATE TABLE `school_student_grade` ( `id` INT NOT NULL AUTO_INCREMENT COMMENT '主键ID', `course_id` INT NOT NULL COMMENT '课程ID', `student_id` INT NOT NULL COMMENT '学生ID', `score` FLOAT DEFAULT 0 COMMENT '成绩', `created_at` date DEFAULT '0-0-0' COMMENT '考试时间', PRIMARY KEY (`id`), FOREIGN KEY student_ref(`student_id`) REFERENCES `school_student_info`(`id`), FOREIGN KEY course_ref(`course_id`) REFERENCES `school_course_info`(`id`) ) COMMENT '学生成绩表';
运算符
比大小
多用于数字类型、字符串类型、日期时间类型。比较结果:1:相等,0:不相等
运算符号:=(<=>)、!=(<>)、>、<、>=、<=
需要注意的是:<=>(安全等于运算符),可以用来判断NULL值
指定范围
BETWEEN a AND b:指定范围查询,必须从结果集中获取
对NULL值的比较
IS NULL / IS NOT NULL
练习一
-- 查询年龄大于12岁的所有学生 SELECT * FROM school_student_info WHERE age > 12; -- 查询年龄在9~12岁之间(含)的学生信息 SELECT * FROM school_student_info WHERE age BETWEEN 9 AND 12; -- 查询未设置/已设置年龄的学生信息 SELECT * FROM school_student_info WHERE age IS NULL; SELECT * FROM school_student_info WHERE age IS NOT NULL;
在/不在列表内
IN (a, b, c) / NOT IN (a, b, c)
最大值
GREATEST(a, b, c)
最小值
LEAST(a, b, c)
如果是字母通过ascii码比较,如果比较的值中存在NULL,则结果为NULL
练习二
-- 查询年龄是9岁和12岁的学生信息 SELECT * FROM school_student_info WHERE age IN (9, 12);
字符串搜索
可以用单引号,也可以用双引号,只要成对匹配就可以。
LIKE运算符支持的两种通配符
练习三
-- 查找所有姓“李”的学生信息 SELECT * FROM school_student_info WHERE stu_name LIKE '李%'; -- 查找所有姓“李”,名只有一个字的学生信息 SELECT * FROM school_student_info WHERE stu_name LIKE '李_'; -- 查找姓名中包含“雪”字的学生信息 SELECT * FROM school_student_info WHERE stu_name LIKE '%雪%';
算法运算符,遵循运算符优先规则。
对于字符串,会做转化(只能处理数字开头,进行截取),不能转化为数字的字符串,会返回0。
练习示例
-- 将学生的年龄加10岁进行展示 SELECT *, age + 10 FROM school_student_info; -- 给所有学生的数学成绩加5分 UPDATE school_student_grade SET score = score + 5 WHERE course_id = 2;
-- 查询所有年龄在9岁到12岁之间的女生 SELECT * FROM school_student_info WHERE age BETWEEN 9 AND 12 AND sex='女'; -- 查询所有12岁以上的男生和9岁以下的女生 SELECT * FROM school_student_info WHERE (age>12 AND sex='男') OR (age<9 AND sex='女'); -- 查询所有“李”姓的女生中年龄不为空的学生信息 SELECT * FROM school_student_info WHERE stu_name LIKE '李%' AND sex='女' AND age IS NOT NULL;
常见函数分类:
常用字符串函数
插入数据时,可以用日期时间函数,创建表时,可以使用系统自带的日期函数变量,比如CURRENT_DATE、CURDATE。
获取当前的日期:CURRENT_DATE()、CURDATE()
获取当前的日期时间:CURRENT_TIMESTAMP()、LOCALTIME()、NOW()、SYSDATE()
获取UTC日期时间:UTC_DATE()、UTC_TIMESTAMP()、UTC_TIME()
日期时间格式化:DATE_FORMAT(date, format)
日期格式化的方式
时间格式化方式
日期增加:DATE_ADD()、ADDDATE()
DATE_ADD(date, INTERVAL expr unit)
日期减少:DATE_SUB()、SUBDATE()
DATE_SUB(date, INTERVAL expr unit)
时间加减:ADDTIME()、SUBTIME()
ADDTIME(expr1, expr2)
加减单位选项
示例
-- 增加本地时间一个小时 SELECT CURRENT_TIMESTAMP,DATE_ADD(CURRENT_TIMESTAMP,INTERVAL 1 HOUR); -- 增加本地时间3小时5分钟 SELECT CURRENT_TIME, ADDTIME(CURRENT_TIME, '03:05:00'); SELECT CURRENT_TIMESTAMP, ADDTIME(CURRENT_TIMESTAMP, '03:05:00'); -- 将考试时间增加1年 SELECT *, ADDDATE(created_at,INTERVAL 1 YEAR) FROM school_student_grade;
-- 统计本班的学生人数 SELECT class_name , COUNT(*) from school_student_info GROUP BY class_name; -- 统计本班语文成绩的最高分/最低分 SELECT MAX(score), MIN(score) from school_student_grade WHERE course_id=1; -- 统计本班语文成绩的平均分 SELECT AVG(score) from school_student_grade WHERE course_id=1; -- 统计学生张三的各科总分 SELECT SUM(score) FROM school_student_grade WHERE student_id=5;
数学函数:
SELECT stu_name, sex, IF(sex='男','帅哥','美女') FROM school_student_info; SELECT VERSION(), MD5('123456'), SHA('123456'); -- 返回在0~50之间(包括0和50) SELECT CEIL(RAND()* 100 % 50);
思考题:现在要为学生寄送期末成绩单,如果发现地址相同的则统一寄送,现需要统计学生的地址信息
-- 方式一:使用DISTINCT关键字去重 SELECT DISTINCT address FROM school_student_info; -- 方式二:使用GROUP BY 分组去重 SELECT address FROM school_student_info GROUP BY address;
分组查询:GROUP BY
SELECT col_name FROM table_name GROUP BY col_name
-- 统计每个班的人数 SELECT class_name, COUNT(*) FROM school_student_info GROUP BY class_name; -- 统计每个班男生、女生的总人数 SELECT class_name, sex, COUNT(sex) FROM school_student_info GROUP BY class_name, sex;
HAVING子句
SELECT col_name FROM table_name GROUP BY col_name HAVING COUNT(1)>2
-- 查找三门成绩都及格(>=60)的学生 SELECT student_id, COUNT(*) FROM school_student_grade WHERE score >= 60 GROUP BY student_id HAVING COUNT(*)=3;
为输出列指定别名
SELECT age [AS] 'my_age' FROM table_name
-- 指定列的别名,为了方便阅读,尽量加上AS关键字 SELECT class_name as '班级', COUNT(*) AS '总人数' FROM school_student_info GROUP BY class_name;
为表指定别名
SELECT t.age FROM table_name [AS] t
-- 指定表的别名 SELECT s.stu_no, s.stu_name FROM school_student_info AS s;
子查询
子查询指一个查询语句嵌套在另一个查询语句内部的查询。
子查询的使用场景:
SELECT 子查询
-- 查询每个学生的学号、姓名、语文成绩 SELECT t1.stu_no AS '学号', t1.stu_name AS '姓名', (SELECT t2.score FROM school_student_grade t2 WHERE t2.course_id=1 AND t2.student_id=t1.id) AS '语文成绩' FROM school_student_info t1;
FROM 子查询:经常被当作临时表
SELECT t.* FROM (SELECT s1.stu_no, s1.stu_name, s1.age * 100 AS age FROM school_student_info s1) t WHERE t.age > 1200;
WHERE 子查询
-- 查询本班语文成绩大于平均成绩的学生ID及分数 SELECT t1.student_id, t1.score FROM school_student_grade t1 WHERE t1.course_id=1 AND t1.score > ( SELECT AVG(t2.score) from school_student_grade t2 WHERE t2.course_id=1); -- 查询本班学生中,没有语文成绩的学生信息 -- 使用IN关键字 SELECT t1.* FROM school_student_info t1 WHERE t1.id NOT IN ( SELECT t2.student_id FROM school_student_grade t2 WHERE t2.course_id=1); -- 使用EXISTS关键字 SELECT t1.* FROM school_student_info t1 WHERE NOT EXISTS ( SELECT t2.* FROM school_student_grade t2 WHERE t2.course_id=1 AND t2.student_id=t1.id);
内连接
SELECT * FROM table1 JOIN table2 ON join_condition
SELECT * FROM table1 JOIN table2 WHERE join_condition
SELECT * FROM table1, table2 WHERE join_condition
-- 查询每个学生的学号、姓名、年龄、课程、老师、语文成绩 -- 方式一:使用 JOIN ON SELECT s1.stu_no, s1.stu_name, s1.age, s3.course_name, s3.teacher, s2.score FROM school_student_info s1 JOIN school_student_grade s2 ON s1.id = s2.student_id JOIN school_course_info s3 ON s2.course_id = s3.id WHERE s2.course_id = 1; -- 方式二:使用 JOIN WHERE SELECT s1.stu_no, s1.stu_name, s1.age, s3.course_name, s3.teacher, s2.score FROM school_student_info s1 JOIN school_student_grade s2 JOIN school_course_info s3 WHERE s1.id = s2.student_id AND s2.course_id = s3.id AND s2.course_id = 1; -- 方式三:使用 , WHERE SELECT s1.stu_no, s1.stu_name, s1.age, s3.course_name, s3.teacher, s2.score FROM school_student_info s1, school_student_grade s2, school_course_info s3 WHERE s1.id = s2.student_id AND s2.course_id = s3.id AND s2.course_id = 1;
自连接
-- 设计一个评论及评论回复表,查询某条评论下的直接回复记录 SELECT t1.content AS '评论', t2.content AS '评论的回复' FROM bbs_comment t1, bbs_comment t2 WHERE t2.parent_id=t1.id;
外连接
-- 缺考的学生信息 SELECT t1.id, t1.stu_no, t1.stu_name, t2.score FROM school_student_info t1 LEFT JOIN school_student_grade t2 ON t1.id=t2.student_id WHERE t2.score IS NULL; -- 缺考了哪一门 SELECT t1.id, t1.stu_no, t1.stu_name, t2.course_id, t2.score FROM school_student_info t1 LEFT JOIN school_student_grade t2 ON t1.id=t2.student_id WHERE t1.stu_no=1037; -- 没有录入的学生信息 SELECT t2.student_id,t2.course_id,t2.score,t1.stu_no, t1.stu_name FROM school_student_info t1 RIGHT JOIN school_student_grade t2 ON t1.id=t2.student_id WHERE t1.stu_no IS NULL;
结果集连接
SELECT * FROM table1 UNION [ALL] SELECT * FROM table2
-- 使用UNION,自动去重 SELECT * FROM school_student_info WHERE id <= 10 UNION SELECT * FROM school_student_info WHERE id <= 15; -- 使用UNION ALL,不去重,返回所有行 SELECT * FROM school_student_info WHERE id <= 10 UNION ALL SELECT * FROM school_student_info WHERE id <= 15;
排序的实现
ORDER BY col_name [ASC | DESC]
排序规则
-- 将三年级所有学生的【语文成绩】根据班级按照从高到低进行排序 SELECT s1.class_name,s1.stu_no, s1.stu_name, s3.course_name, s2.score FROM school_student_info s1, school_student_grade s2, school_course_info s3 WHERE s1.id=s2.student_id AND s2.course_id=s3.id AND s2.course_id = 1 ORDER BY s1.class_name, s2.score DESC; -- 将三年级所有学生的期末考试总成绩按照从高到低进行排序 SELECT s1.stu_no, s1.stu_name, SUM(s2.score) AS score FROM school_student_info s1, school_student_grade s2 WHERE s1.id=s2.student_id GROUP BY s2.student_id ORDER BY score DESC;
分页的好处
分页的实现
LIMIT [起始位置,] 偏移量
,偏移量:每一页数据的大小SELECT * FROM table_name LIMIT 10;
-- 三年级所有学生中语文成绩最好的前10名 SELECT s1.class_name,s1.stu_no, s1.stu_name, s3.course_name, s2.score FROM school_student_info s1, school_student_grade s2, school_course_info s3 WHERE s1.id=s2.student_id AND s2.course_id=s3.id AND s2.course_id = 1 ORDER BY s2.score DESC LIMIT 10; -- 三年级所有学生中期末考试总成绩的第11~第20名 SELECT s1.stu_no, s1.stu_name, SUM(s2.score) AS score FROM school_student_info s1, school_student_grade s2 WHERE s1.id=s2.student_id GROUP BY s2.student_id ORDER BY score DESC LIMIT 10, 10;