一,数据库的约束
1,约束类型
|---|-------------|---------------------------------------------|
| 1 | not null | 非空约束,标记这个字段不可以为空 |
| 2 | unique | 唯一约束,标记这个字段的值是该列唯一的值,在这一列的其他行,不可以与该字段相等 |
| 3 | default | 默认约束,在该字段没有赋值时,使用默认值填充该列 |
| 4 | primary key | 主键约束,相当于not null + unique |
| 5 | foreign key | 外键约束,与其他表的主键简历联系,在添加或修改数据是,会根据主外键关系检查数据是否合法 |
1,not null
试着使用not null 来创建数据表
sql
create table if not exists student(
-> id bigint not null,
-> name varchar(20) not null
-> );
sql
desc student;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | bigint | NO | | NULL | |
| name | varchar(20) | NO | | NULL | |
+-------+-------------+------+-----+---------+-------+
我们看到在null的列,两个字段都不允许为空,我们添加两行不为空和一行为空的数据来试一下。
sql
insert into student values (1,'张三'),(2,'李四');
sql
select * from student;
+----+--------+
| id | name |
+----+--------+
| 1 | 张三 |
| 2 | 李四 |
+----+--------+
成功添加
sql
insert into student values (null,null);
ERROR 1048 (23000): Column 'id' cannot be null
在新增数据发生报错,它不允许字段id为空。
2,unique
在试着用unique来创建一个表
sql
create table if not exists student(
-> id bigint unique,
-> name varchar(20) unique
-> );
sql
desc student;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | bigint | YES | UNI | NULL | |
| name | varchar(20) | YES | UNI | NULL | |
+-------+-------------+------+-----+---------+-------+
key 变成了唯一类型
我们添加三个数据,两个相同的,一个不同的
sql
insert into student values (1,'张三'),(2,'李四');
Query OK, 2 rows affected (0.00 sec)
成功添加了,
sql
insert into student values (1,'王五');
ERROR 1062 (23000): Duplicate entry '1' for key 'student.id'
sql
insert into student values (3,'张三');
ERROR 1062 (23000): Duplicate entry '张三' for key 'student.name'
两个字段都设置为唯一类型的,所以无论哪一个字段重复了都不可以。
3,default
sql
create table if not exists student(
-> id bigint default 0,
-> name varchar(20) default '无名氏' unique
-> );
这些数据库约束是可以一起使用的,
sql
desc student;
+-------+-------------+------+-----+-----------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+-----------+-------+
| id | bigint | YES | | 0 | |
| name | varchar(20) | YES | UNI | 无名氏 | |
+-------+-------------+------+-----+-----------+-------+
我们来添加两个啥都没有的数据
sql
insert into student (id) values (1);
Query OK, 1 row affected (0.00 sec)
mysql> insert into student (name) values ('张三');
Query OK, 1 row affected (0.00 sec)
sql
select * from student;
+------+-----------+
| id | name |
+------+-----------+
| 1 | 无名氏 |
| 0 | 张三 |
+------+-----------+
空缺的元素都由默认值填补了。
4,primary key
可以使用auto_increment来在主键后面,这样就代表这个字段是自增主键,不用对其进行赋值,在其他列的插入时,就会自行生成对应的id,但是如果我们这行sql语句写错了的话id是不会接着上一行数据的id继续的,
sql
create table if not exists student(
-> id bigint primary key auto_increment,
-> name varchar(20)
-> );
复合主键
sql
create table if not exists student(
-> id bigint,
-> name varchar(20),
-> primary key(id,name)
-> );
sql
desc student;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | bigint | NO | PRI | NULL | |
| name | varchar(20) | NO | PRI | NULL | |
+-------+-------------+------+-----+---------+-------+
5,foreign key
sql
create table if not exists student(
-> id bigint primary key auto_increment,
-> name varchar(20),
-> class_id bigint,
-> foreign key (class_id) references class(id)
-> );
sql
desc student;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | bigint | NO | PRI | NULL | auto_increment |
| name | varchar(20) | YES | | NULL | |
| class_id | bigint | YES | MUL | NULL | |
+----------+-------------+------+-----+---------+----------------+
有了外键到约束我们就不能随便插入数据了
sql
select * from class;
+----+---------+
| id | name |
+----+---------+
| 1 | java113 |
| 2 | java112 |
| 3 | java111 |
+----+---------+
我们班级表新增三个班级
sql
select * from student;
+----+--------+----------+
| id | name | class_id |
+----+--------+----------+
| 1 | 张三 | 1 |
| 2 | 李四 | 2 |
| 3 | 王五 | 3 |
+----+--------+----------+
再给每个班级新增一个学生
我们再试着给学生表中添加一个4班的学生,但是班级表是不存在编号为4的班级的
sql
insert into student (name,class_id) values ('张三','4');
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`java113`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`))
因为外键约束,我们无法添加class表中没有的班级的学生编号
二,表的设计
1,三大范式
1,第一范式:要求表中的每一列不可再分,其实就是数据库提供的数据类型能描述这个字段,如果不满足第一范式,那么数据库就不是关系型数据库
2,第二范式:在满足第一范式的基础上,消除部分函数依赖,只能出现在有复合主键的表上,如果有一列字段只依赖于复合主键的其中一列,就需要移除这个列,单独建表。如果不满足第二范式就会出现删除异常,新增异常,更新异常,数据冗余
3,第三范式:在第二范式的基础上,消除传递依赖,这个是如果除主键外的某一列,对其他某一列存在依赖时,我们就要移除这个列
2,关系模型
1,一对一模型:
各自建立各自的表,在一个表中添加一个字段完成对另一个表的引用。
2,一对多模型:
各自建立各自的表,在一表中设置主键,在多表中设置外键于一表主键关联。
3,多对多模型:
各自建立各自的表,另外添加一个新的关系表。
我们举个多对多模型的例子,
一个class表
sql
> create table if not exists class (
-> id bigint primary key auto_increment,
-> name varchar(20)
-> );
一个student表
sql
create table if not exists student(
-> id bigint primary key auto_increment,
-> name varchar(20)
-> );
一个sorce表来关联这两个表
sql
create table if not exists sorce(
-> id bigint primary key auto_increment,
-> student_id bigint,
-> class_id bigint,
-> stu_score decimal(3,1),
-> foreign key (student_id) references student(id),
-> foreign key (class_id) references class(id)
-> );
这就形成了多对多关系
三,查询(进阶)
1,插入时查询
语法:
insert into 新表名 (列名) select 要复制的列名(这里不要使用括号)from 旧表名
这个我们可以用到表复制的时候
sql
select * from student;
+----+---------+
| id | name |
+----+---------+
| 1 | 张三 |
| 2 | 0李四 |
| 3 | 王五 |
+----+---------+
我们现在创建一个新表,直接将旧表的数据复制到新表中
sql
create table if not exists new_student(
-> id bigint primary key auto_increment,
-> name varchar(20)
-> );
sql
insert into new_student (id,name) select id,name from student;
2,聚合函数
sql
select * from course;
+-----------+--------------------+
| course_id | name |
+-----------+--------------------+
| 1 | Java |
| 2 | 中国传统文化 |
| 3 | 计算机原理 |
| 4 | 语文 |
| 5 | 高阶数学 |
| 6 | 英文 |
+-----------+--------------------+
sql
select * from class;
+----------+-------------------------+
| class_id | name |
+----------+-------------------------+
| 1 | 计算机系2019级1班 |
| 2 | 中文系2019级3班 |
| 3 | 自动化2019级5班 |
+----------+-------------------------+
sql
select * from student;
+------------+-------+-----------------+------------------+----------+
| student_id | sn | name | mail | class_id |
+------------+-------+-----------------+------------------+----------+
| 1 | 09982 | 黑旋风李逵 | xuanfeng@qq.com | 1 |
| 2 | 00835 | 菩提老祖 | NULL | 1 |
| 3 | 00391 | 白素贞 | NULL | 1 |
| 4 | 00031 | 许仙 | xuxian@qq.com | 1 |
| 5 | 00054 | 不想毕业 | NULL | 1 |
| 6 | 51234 | 好好说话 | say@qq.com | 2 |
| 7 | 83223 | tellme | NULL | 2 |
| 8 | 09527 | 老外学中文 | foreigner@qq.com | 2 |
+------------+-------+-----------------+------------------+----------+
sql
select * from exam;
+------+-----------+---------+------+---------+
| id | name | chinese | math | english |
+------+-----------+---------+------+---------+
| 1 | 唐三藏 | 67.0 | 98.0 | 56.0 |
| 2 | 孙悟空 | 87.5 | 78.0 | 77.0 |
| 3 | 猪悟能 | 88.0 | 98.0 | 90.0 |
| 4 | 曹孟德 | 82.0 | 84.0 | 67.0 |
| 5 | 刘玄德 | 55.5 | 85.0 | 45.0 |
| 6 | 孙权 | 70.0 | 73.0 | 78.5 |
| 7 | 宋公明 | 75.0 | 65.0 | 30.0 |
+------+-----------+---------+------+---------+
sql
mysql> select * from emp;
+----+-----------+--------------+------------+
| id | name | role | salary |
+----+-----------+--------------+------------+
| 1 | 马云 | 老板 | 1500000.00 |
| 2 | 马化腾 | 老板 | 1800000.00 |
| 3 | 鑫哥 | 讲师 | 10000.00 |
| 4 | 博哥 | 讲师 | 12000.00 |
| 5 | 平姐 | 学管 | 9000.00 |
| 6 | 莹姐 | 学管 | 8000.00 |
| 7 | 猪悟能 | 游戏角色 | 700.50 |
| 8 | 沙和尚 | 游戏角色 | 333.30 |
+----+-----------+--------------+------------+
sql
select * from score;
+----------+------------+-----------+-------+
| score_id | student_id | course_id | score |
+----------+------------+-----------+-------+
| 1 | 1 | 1 | 70.50 |
| 2 | 1 | 3 | 98.50 |
| 3 | 1 | 5 | 33.00 |
| 4 | 1 | 6 | 98.00 |
| 5 | 2 | 1 | 60.00 |
| 6 | 2 | 5 | 59.50 |
| 7 | 3 | 1 | 33.00 |
| 8 | 3 | 3 | 68.00 |
| 9 | 3 | 5 | 99.00 |
| 10 | 4 | 1 | 67.00 |
| 11 | 4 | 3 | 23.00 |
| 12 | 4 | 5 | 56.00 |
| 13 | 4 | 6 | 72.00 |
| 14 | 5 | 1 | 81.00 |
| 15 | 5 | 5 | 37.00 |
| 16 | 6 | 2 | 56.00 |
| 17 | 6 | 4 | 43.00 |
| 18 | 6 | 6 | 79.00 |
| 19 | 7 | 2 | 80.00 |
| 20 | 7 | 6 | 92.00 |
+----------+------------+-----------+-------+
我们拿这几个表来举例子。
1,count(列):统计一列的个数
------------1,统计班级有多少同学
sql
select count(*) from exam;
+----------+
| count(*) |
+----------+
| 7 |
+----------+
------------2,统计班级收集的 qq_mail 有多少个,qq_mail 为 NULL 的数据不会计入结果
sql
select count(mail) from student
-> ;
+-------------+
| count(mail) |
+-------------+
| 4 |
+-------------+
2,Sum(列):求和
------------1,统计数学成绩总分
sql
select sum(math) from exam;
+-----------+
| sum(math) |
+-----------+
| 581.0 |
+-----------+
------------2,不及格 < 60 的总分,没有结果,返回 NULL
sql
select sum(math) from exam where math<60;
+-----------+
| sum(math) |
+-----------+
| NULL |
+-----------+
3,AVG(列):求平均值
------------1,统计平均总分
sql
select avg(english) from exam;
+--------------+
| avg(english) |
+--------------+
| 63.35714 |
+--------------+
4,MAX(列):求最大值
------------1,返回英语最高分
sql
select max(english) from exam;
+--------------+
| max(english) |
+--------------+
| 90.0 |
+--------------+
5,MIN(列):求最小值
------------1,返回 > 70 分以上的数学最低分
sql
select min(math) from exam where math>70;
+-----------+
| min(math) |
+-----------+
| 73.0 |
+-----------+
3,group by
group by 语句就是分组查询
语法:
select 字段1 字段2 from 表名 group by 字段1 ,字段2;
group by是可以使用别名的,但是where不行
sql
select * from emp;
+----+-----------+--------------+------------+
| id | name | role | salary |
+----+-----------+--------------+------------+
| 1 | 马云 | 老板 | 1500000.00 |
| 2 | 马化腾 | 老板 | 1800000.00 |
| 3 | 鑫哥 | 讲师 | 10000.00 |
| 4 | 博哥 | 讲师 | 12000.00 |
| 5 | 平姐 | 学管 | 9000.00 |
| 6 | 莹姐 | 学管 | 8000.00 |
| 7 | 猪悟能 | 游戏角色 | 700.50 |
| 8 | 沙和尚 | 游戏角色 | 333.30 |
+----+-----------+--------------+------------+
我们使用这个表
------------1,查询每个角色的最高工资、最低工资和平均工资
sql
select role,max(salary),min(salary),avg(salary) from emp group by role;
+--------------+-------------+-------------+----------------+
| role | max(salary) | min(salary) | avg(salary) |
+--------------+-------------+-------------+----------------+
| 老板 | 1800000.00 | 1500000.00 | 1650000.000000 |
| 讲师 | 12000.00 | 10000.00 | 11000.000000 |
| 学管 | 9000.00 | 8000.00 | 8500.000000 |
| 游戏角色 | 700.50 | 333.30 | 516.900000 |
+--------------+-------------+-------------+----------------+
4,Having
我们使用group by 的时候不能使用where字句,所以出现了Having,我们使用Having来过滤条件;
------------1,显示平均工资低于1500的角色和它的平均工资
sql
select role,avg(salary) from emp group by role having avg(salary)<1500;
+--------------+-------------+
| role | avg(salary) |
+--------------+-------------+
| 游戏角色 | 516.900000 |
+--------------+-------------+
5,联合查询
对多张表进行取笛卡尔积,在选取正确的联合表;
1,内连接
语法:
select 表1 别名,表2 别名 where 连接条件 and 其他条件
select 表1 别名 [inner] join 表2 别名2 on 连接条件 and 其他条件
------------1,查询"许仙"同学的 成绩
sql
select stu.name,sc.score from student stu,score sc where sc.student_id = stu.student_id and stu.name = '许仙';
+--------+-------+
| name | score |
+--------+-------+
| 许仙 | 67.00 |
| 许仙 | 23.00 |
| 许仙 | 56.00 |
| 许仙 | 72.00 |
+--------+-------+
sql
select stu.name,sc.score from student stu inner join score sc on stu.student_id = sc.student_id where stu.name = '许仙';
+--------+-------+
| name | score |
+--------+-------+
| 许仙 | 67.00 |
| 许仙 | 23.00 |
| 许仙 | 56.00 |
| 许仙 | 72.00 |
+--------+-------+
------------2,查询所有同学的总成绩,及同学的个人信息:
sql
select stu.name,stu.sn,stu.mail,sum(sc.score) from student stu,score sc where stu.student_id = sc.student_id group by stu.student_id;
+-----------------+-------+-----------------+---------------+
| name | sn | mail | sum(sc.score) |
+-----------------+-------+-----------------+---------------+
| 黑旋风李逵 | 09982 | xuanfeng@qq.com | 300.00 |
| 菩提老祖 | 00835 | NULL | 119.50 |
| 白素贞 | 00391 | NULL | 200.00 |
| 许仙 | 00031 | xuxian@qq.com | 218.00 |
| 不想毕业 | 00054 | NULL | 118.00 |
| 好好说话 | 51234 | say@qq.com | 178.00 |
| tellme | 83223 | NULL | 172.00 |
+-----------------+-------+-----------------+---------------+
sql
select stu.sn,stu.name,stu.mail,sum(sc.score) from student stu inner join score sc on stu.student_id = sc.student_id group by stu.student_id;
+-------+-----------------+-----------------+---------------+
| sn | name | mail | sum(sc.score) |
+-------+-----------------+-----------------+---------------+
| 09982 | 黑旋风李逵 | xuanfeng@qq.com | 300.00 |
| 00835 | 菩提老祖 | NULL | 119.50 |
| 00391 | 白素贞 | NULL | 200.00 |
| 00031 | 许仙 | xuxian@qq.com | 218.00 |
| 00054 | 不想毕业 | NULL | 118.00 |
| 51234 | 好好说话 | say@qq.com | 178.00 |
| 83223 | tellme | NULL | 172.00 |
+-------+-----------------+-----------------+---------------+
------------3,查询所有同学的成绩,及同学的个人信息
sql
select stu.sn,stu.name,stu.mail,sc.score from student stu,score sc where stu.student_id = sc.student_id;
+-------+-----------------+-----------------+-------+
| sn | name | mail | score |
+-------+-----------------+-----------------+-------+
| 09982 | 黑旋风李逵 | xuanfeng@qq.com | 70.50 |
| 09982 | 黑旋风李逵 | xuanfeng@qq.com | 98.50 |
| 09982 | 黑旋风李逵 | xuanfeng@qq.com | 33.00 |
| 09982 | 黑旋风李逵 | xuanfeng@qq.com | 98.00 |
| 00835 | 菩提老祖 | NULL | 60.00 |
| 00835 | 菩提老祖 | NULL | 59.50 |
| 00391 | 白素贞 | NULL | 33.00 |
| 00391 | 白素贞 | NULL | 68.00 |
| 00391 | 白素贞 | NULL | 99.00 |
| 00031 | 许仙 | xuxian@qq.com | 67.00 |
| 00031 | 许仙 | xuxian@qq.com | 23.00 |
| 00031 | 许仙 | xuxian@qq.com | 56.00 |
| 00031 | 许仙 | xuxian@qq.com | 72.00 |
| 00054 | 不想毕业 | NULL | 81.00 |
| 00054 | 不想毕业 | NULL | 37.00 |
| 51234 | 好好说话 | say@qq.com | 56.00 |
| 51234 | 好好说话 | say@qq.com | 43.00 |
| 51234 | 好好说话 | say@qq.com | 79.00 |
| 83223 | tellme | NULL | 80.00 |
| 83223 | tellme | NULL | 92.00 |
+-------+-----------------+-----------------+-------+
sql
select stu.sn,stu.name,stu.mail,sc.score from student stu inner join score sc on stu.student_id = sc.student_id;
+-------+-----------------+-----------------+-------+
| sn | name | mail | score |
+-------+-----------------+-----------------+-------+
| 09982 | 黑旋风李逵 | xuanfeng@qq.com | 70.50 |
| 09982 | 黑旋风李逵 | xuanfeng@qq.com | 98.50 |
| 09982 | 黑旋风李逵 | xuanfeng@qq.com | 33.00 |
| 09982 | 黑旋风李逵 | xuanfeng@qq.com | 98.00 |
| 00835 | 菩提老祖 | NULL | 60.00 |
| 00835 | 菩提老祖 | NULL | 59.50 |
| 00391 | 白素贞 | NULL | 33.00 |
| 00391 | 白素贞 | NULL | 68.00 |
| 00391 | 白素贞 | NULL | 99.00 |
| 00031 | 许仙 | xuxian@qq.com | 67.00 |
| 00031 | 许仙 | xuxian@qq.com | 23.00 |
| 00031 | 许仙 | xuxian@qq.com | 56.00 |
| 00031 | 许仙 | xuxian@qq.com | 72.00 |
| 00054 | 不想毕业 | NULL | 81.00 |
| 00054 | 不想毕业 | NULL | 37.00 |
| 51234 | 好好说话 | say@qq.com | 56.00 |
| 51234 | 好好说话 | say@qq.com | 43.00 |
| 51234 | 好好说话 | say@qq.com | 79.00 |
| 83223 | tellme | NULL | 80.00 |
| 83223 | tellme | NULL | 92.00 |
+-------+-----------------+-----------------+-------+
2,外连接
外连接分为左外连接和右外连接。如果联合查询,左侧的表完全显示我们就说是左外连接;右侧的表完 全显示我们就说是右外连接。
------------左外连接,表1完全显示
语法:
select 字段名 from 表名1 left join 表名2 on 连接条件
------------右外连接,表2完全显示
语法
select 字段名 from 表名1 right join 表名2 on 连接条件
------------1,显示,"老外学中文"同学的考试成绩 ,没有考试成绩也要显示
sql
select stu.sn,stu.name,stu.mail,sc.score from student stu left join score sc on stu.student_id = sc.student_id;
+-------+-----------------+------------------+-------+
| sn | name | mail | score |
+-------+-----------------+------------------+-------+
| 09982 | 黑旋风李逵 | xuanfeng@qq.com | 70.50 |
| 09982 | 黑旋风李逵 | xuanfeng@qq.com | 98.50 |
| 09982 | 黑旋风李逵 | xuanfeng@qq.com | 33.00 |
| 09982 | 黑旋风李逵 | xuanfeng@qq.com | 98.00 |
| 00835 | 菩提老祖 | NULL | 60.00 |
| 00835 | 菩提老祖 | NULL | 59.50 |
| 00391 | 白素贞 | NULL | 33.00 |
| 00391 | 白素贞 | NULL | 68.00 |
| 00391 | 白素贞 | NULL | 99.00 |
| 00031 | 许仙 | xuxian@qq.com | 67.00 |
| 00031 | 许仙 | xuxian@qq.com | 23.00 |
| 00031 | 许仙 | xuxian@qq.com | 56.00 |
| 00031 | 许仙 | xuxian@qq.com | 72.00 |
| 00054 | 不想毕业 | NULL | 81.00 |
| 00054 | 不想毕业 | NULL | 37.00 |
| 51234 | 好好说话 | say@qq.com | 56.00 |
| 51234 | 好好说话 | say@qq.com | 43.00 |
| 51234 | 好好说话 | say@qq.com | 79.00 |
| 83223 | tellme | NULL | 80.00 |
| 83223 | tellme | NULL | 92.00 |
| 09527 | 老外学中文 | foreigner@qq.com | NULL |
+-------+-----------------+------------------+-------+
------------2,学生表、成绩表、课程表3张表关联查询
sql
select stu.sn,stu.name,stu.mail,sc.score,co.name from student stu left join score sc on stu.student_id = sc.student_id left join course co on sc.course_id = co.course_id;
+-------+-----------------+------------------+-------+--------------------+
| sn | name | mail | score | name |
+-------+-----------------+------------------+-------+--------------------+
| 09982 | 黑旋风李逵 | xuanfeng@qq.com | 70.50 | Java |
| 09982 | 黑旋风李逵 | xuanfeng@qq.com | 98.50 | 计算机原理 |
| 09982 | 黑旋风李逵 | xuanfeng@qq.com | 33.00 | 高阶数学 |
| 09982 | 黑旋风李逵 | xuanfeng@qq.com | 98.00 | 英文 |
| 00835 | 菩提老祖 | NULL | 60.00 | Java |
| 00835 | 菩提老祖 | NULL | 59.50 | 高阶数学 |
| 00391 | 白素贞 | NULL | 33.00 | Java |
| 00391 | 白素贞 | NULL | 68.00 | 计算机原理 |
| 00391 | 白素贞 | NULL | 99.00 | 高阶数学 |
| 00031 | 许仙 | xuxian@qq.com | 67.00 | Java |
| 00031 | 许仙 | xuxian@qq.com | 23.00 | 计算机原理 |
| 00031 | 许仙 | xuxian@qq.com | 56.00 | 高阶数学 |
| 00031 | 许仙 | xuxian@qq.com | 72.00 | 英文 |
| 00054 | 不想毕业 | NULL | 81.00 | Java |
| 00054 | 不想毕业 | NULL | 37.00 | 高阶数学 |
| 51234 | 好好说话 | say@qq.com | 56.00 | 中国传统文化 |
| 51234 | 好好说话 | say@qq.com | 43.00 | 语文 |
| 51234 | 好好说话 | say@qq.com | 79.00 | 英文 |
| 83223 | tellme | NULL | 80.00 | 中国传统文化 |
| 83223 | tellme | NULL | 92.00 | 英文 |
| 09527 | 老外学中文 | foreigner@qq.com | NULL | NULL |
+-------+-----------------+------------------+-------+--------------------+
3,自连接
自连接是在同一张表中进行查询,表要起两个不同的别名
------------1,显示所有"计算机原理"成绩比"Java"成绩高的成绩信息
这个我们来分析一下,计算机原理和java是课程表中,成绩是score表的内容,要取这两个表的笛卡尔积,java的course_id = 1,计算机原理的course_id = 3,这次我们不是比列而是行与行,
sql
select * from score sc1,score sc2 where sc1.course_id = 1 and sc2.course_id = 3 and sc2.score > sc1.score and sc1.student_id = sc2.student_id;
+----------+------------+-----------+-------+----------+------------+-----------+-------+
| score_id | student_id | course_id | score | score_id | student_id | course_id | score |
+----------+------------+-----------+-------+----------+------------+-----------+-------+
| 1 | 1 | 1 | 70.50 | 2 | 1 | 3 | 98.50 |
| 7 | 3 | 1 | 33.00 | 8 | 3 | 3 | 68.00 |
+----------+------------+-----------+-------+----------+------------+-----------+-------+
4,子查询
子查询就是嵌套查询,
------------1,查询与"不想毕业" 同学的同班同学:
sql
select * from student where class_id = (select class_id from student where name = '不想毕业');
+------------+-------+-----------------+-----------------+----------+
| student_id | sn | name | mail | class_id |
+------------+-------+-----------------+-----------------+----------+
| 1 | 09982 | 黑旋风李逵 | xuanfeng@qq.com | 1 |
| 2 | 00835 | 菩提老祖 | NULL | 1 |
| 3 | 00391 | 白素贞 | NULL | 1 |
| 4 | 00031 | 许仙 | xuxian@qq.com | 1 |
| 5 | 00054 | 不想毕业 | NULL | 1 |
+------------+-------+-----------------+-----------------+----------+
------------2,查询"语文"或"英文"课程的成绩信息
sql
select * from score where course_id in (select course_id from course where name = '语文' or name = '英文');
+----------+------------+-----------+-------+
| score_id | student_id | course_id | score |
+----------+------------+-----------+-------+
| 17 | 6 | 4 | 43.00 |
| 4 | 1 | 6 | 98.00 |
| 13 | 4 | 6 | 72.00 |
| 18 | 6 | 6 | 79.00 |
| 20 | 7 | 6 | 92.00 |
+----------+------------+-----------+-------+
exists 关键字
这个是如果子查询的语句有返回语句,整体查询语句就执行,反之不执行,
sql
select * from score where not exists (select course_id from course where name = '语文' or name = '英文');
Empty set (0.00 sec)
sql
select * from score where exists (select course_id from course where name = '语文' or name = '英文');
+----------+------------+-----------+-------+
| score_id | student_id | course_id | score |
+----------+------------+-----------+-------+
| 1 | 1 | 1 | 70.50 |
| 2 | 1 | 3 | 98.50 |
| 3 | 1 | 5 | 33.00 |
| 4 | 1 | 6 | 98.00 |
| 5 | 2 | 1 | 60.00 |
| 6 | 2 | 5 | 59.50 |
| 7 | 3 | 1 | 33.00 |
| 8 | 3 | 3 | 68.00 |
| 9 | 3 | 5 | 99.00 |
| 10 | 4 | 1 | 67.00 |
| 11 | 4 | 3 | 23.00 |
| 12 | 4 | 5 | 56.00 |
| 13 | 4 | 6 | 72.00 |
| 14 | 5 | 1 | 81.00 |
| 15 | 5 | 5 | 37.00 |
| 16 | 6 | 2 | 56.00 |
| 17 | 6 | 4 | 43.00 |
| 18 | 6 | 6 | 79.00 |
| 19 | 7 | 2 | 80.00 |
| 20 | 7 | 6 | 92.00 |
+----------+------------+-----------+-------+
------------1,查询所有比"中文系2019级3班"平均分高的成绩信息:
sql
select * from score sc where sc.score > (select avg(score) from score sc,class cl,student stu where cl.class_id = stu.class_id and sc.student_id = stu.student_id and cl.name = '中文系2019级3班');
+----------+------------+-----------+-------+
| score_id | student_id | course_id | score |
+----------+------------+-----------+-------+
| 1 | 1 | 1 | 70.50 |
| 2 | 1 | 3 | 98.50 |
| 4 | 1 | 6 | 98.00 |
| 9 | 3 | 5 | 99.00 |
| 13 | 4 | 6 | 72.00 |
| 14 | 5 | 1 | 81.00 |
| 18 | 6 | 6 | 79.00 |
| 19 | 7 | 2 | 80.00 |
| 20 | 7 | 6 | 92.00 |
+----------+------------+-----------+-------+
5,合并查询
去重union
不去重 union all
比如查询id<3,或者名字为英文的课程
sql
select * from course where course_id<3 union select * from course where name = '英文';
+-----------+--------------------+
| course_id | name |
+-----------+--------------------+
| 1 | Java |
| 2 | 中国传统文化 |
| 6 | 英文 |
+-----------+--------------------+
union all可以去重,这里就不演示了。