1.启动数据库服务
C:\Windows\system32>net start mysql57
MySQL57 服务正在启动 .
MySQL57 服务已经启动成功。
2.登陆数据库
C:\Windows\system32>mysql -u root -p
Enter password: *********
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.17-log MySQL Community Server (GPL)
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
3.查询数据库服务器中所有的数据库
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| kaige |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
6 rows in set (0.02 sec)
4.选中某个数据库进行操作
mysql> use test;
Database changed
5.退出数据库服务器
mysql> exit;
bye
6.在数据库服务器中创建我们的数据库
mysql> create database test1;
Query OK, 1 row affected (0.00 sec)
7.查看某个数据库中的所有的数据表
mysql> show tables;
+-----------------+
| Tables_in_test1 |
+-----------------+
| pet |
+-----------------+
1 row in set (0.01 sec)
8.在某个数据库中创建数据表
mysql> CREATE TABLE pet(
-> name VARCHAR(20),
-> owner VARCHAR(20),
-> species VARCHAR(20),
-> sex CHAR(1),
-> birth DATE,
-> death DATE);
Query OK, 0 rows affected (0.03 sec)
9.查看数据表的结构详情
mysql> describe pet;
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| name | varchar(20) | YES | | NULL | |
| owner | varchar(20) | YES | | NULL | |
| species | varchar(20) | YES | | NULL | |
| sex | char(1) | YES | | NULL | |
| birth | date | YES | | NULL | |
| death | date | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
6 rows in set (0.01 sec)
10.往数据表中添加数据记录
mysql> INSERT INTO pet
-> values ("Puffball","Diane","hamster","f","1999-03-30",NULL);
Query OK, 1 row affected (0.01 sec)
mysql> select * from pet;
+----------+-------+---------+------+------------+-------+
| name | owner | species | sex | birth | death |
+----------+-------+---------+------+------------+-------+
| Puffball | Diane | hamster | f | 1999-03-30 | NULL |
+----------+-------+---------+------+------------+-------+
mysql> INSERT INTO pet VALUES('Claws','Gwen','cat','m','1994-03-17',NULL);INSERT INTO pet VALUES('Buffy','Harold','dog','f','1989-05-13',NULL);INSERT INTO pet VALUES('Fang','Benny','dog','m','1990-08-27',NULL);INSERT INTO pet VALUES('Bowser','Diane','dog','m','1979-08-31','1995-07-29');INSERT INTO pet VALUES('Chirpy','Gwen','bird','f','1998-09-11',NULL);
Query OK, 1 row affected (0.00 sec)
Query OK, 1 row affected (0.00 sec)
Query OK, 1 row affected (0.00 sec)
Query OK, 1 row affected (0.00 sec)
Query OK, 1 row affected (0.00 sec)
mysql> select * from pet;
+----------+--------+---------+------+------------+------------+
| name | owner | species | sex | birth | death |
+----------+--------+---------+------+------------+------------+
| Puffball | Diane | hamster | f | 1999-03-30 | NULL |
| 旺财 | 周星驰 | 狗 | m | 1999-01-01 | NULL |
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
| Fang | Benny | dog | m | 1990-08-27 | NULL |
| Bowser | Diane | dog | m | 1979-08-31 | 1995-07-29 |
| Chirpy | Gwen | bird | f | 1998-09-11 | NULL |
| Claws | Gwen | cat | m | 1994-03-17 | NULL |
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
| Fang | Benny | dog | m | 1990-08-27 | NULL |
| Bowser | Diane | dog | m | 1979-08-31 | 1995-07-29 |
| Chirpy | Gwen | bird | f | 1998-09-11 | NULL |
| Claws | Gwen | cat | m | 1994-03-17 | NULL |
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
| Fang | Benny | dog | m | 1990-08-27 | NULL |
| Bowser | Diane | dog | m | 1979-08-31 | 1995-07-29 |
| Chirpy | Gwen | bird | f | 1998-09-11 | NULL |
+----------+--------+---------+------+------------+------------+
16 rows in set (0.00 sec)
11.mysql常用数据类型
MySQL 数据类型
12.删除数据
mysql> delete from pet where name="Buffy";
Query OK, 3 rows affected (0.01 sec)
13.修改数据
mysql> update pet set name="fang";
Query OK, 13 rows affected (0.01 sec)
Rows matched: 13 Changed: 13 Warnings: 0
mysql> select * from pet;
+------+--------+---------+------+------------+------------+
| name | owner | species | sex | birth | death |
+------+--------+---------+------+------------+------------+
| fang | Diane | hamster | f | 1999-03-30 | NULL |
| fang | 周星驰 | 狗 | m | 1999-01-01 | NULL |
| fang | Benny | dog | m | 1990-08-27 | NULL |
| fang | Diane | dog | m | 1979-08-31 | 1995-07-29 |
| fang | Gwen | bird | f | 1998-09-11 | NULL |
| fang | Gwen | cat | m | 1994-03-17 | NULL |
| fang | Benny | dog | m | 1990-08-27 | NULL |
| fang | Diane | dog | m | 1979-08-31 | 1995-07-29 |
| fang | Gwen | bird | f | 1998-09-11 | NULL |
| fang | Gwen | cat | m | 1994-03-17 | NULL |
| fang | Benny | dog | m | 1990-08-27 | NULL |
| fang | Diane | dog | m | 1979-08-31 | 1995-07-29 |
| fang | Gwen | bird | f | 1998-09-11 | NULL |
+------+--------+---------+------+------------+------------+
mysql> update pet set name = "汪汪" where owner="周星驰";
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from pet;
+------+--------+---------+------+------------+------------+
| name | owner | species | sex | birth | death |
+------+--------+---------+------+------------+------------+
| fang | Diane | hamster | f | 1999-03-30 | NULL |
| 汪汪 | 周星驰 | 狗 | m | 1999-01-01 | NULL |
| fang | Benny | dog | m | 1990-08-27 | NULL |
| fang | Diane | dog | m | 1979-08-31 | 1995-07-29 |
| fang | Gwen | bird | f | 1998-09-11 | NULL |
| fang | Gwen | cat | m | 1994-03-17 | NULL |
| fang | Benny | dog | m | 1990-08-27 | NULL |
| fang | Diane | dog | m | 1979-08-31 | 1995-07-29 |
| fang | Gwen | bird | f | 1998-09-11 | NULL |
| fang | Gwen | cat | m | 1994-03-17 | NULL |
| fang | Benny | dog | m | 1990-08-27 | NULL |
| fang | Diane | dog | m | 1979-08-31 | 1995-07-29 |
| fang | Gwen | bird | f | 1998-09-11 | NULL |
+------+--------+---------+------+------------+------------+
13 rows in set (0.00 sec)
14.mysql建表约束
14.1.主键约束
他能够唯一确定一张表中的一条记录,也就是我们通过给某个字段添加约束,就可以使得该字段不重复且不为空
mysql> create table user(
-> id int primary key,
-> name varchar(20)
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> show tables;
+-----------------+
| Tables_in_test1 |
+-----------------+
| pet |
| user |
+-----------------+
2 rows in set (0.00 sec)
mysql> describe user;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> insert into user values(1,"张三");
Query OK, 1 row affected (0.01 sec)
mysql> insert into user values(1,"张三");
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
mysql> insert into user values(2,"张三");
Query OK, 1 row affected (0.01 sec)
mysql> select * from user;
+----+------+
| id | name |
+----+------+
| 1 | 张三 |
| 2 | 张三 |
+----+------+
2 rows in set (0.00 sec)
mysql> insert into user values(NULL,"张三");
ERROR 1048 (23000): Column 'id' cannot be null
14.1.1联合主键
只要联合的主键值加起来不重复就可以
mysql> create table user2(
-> id int,
-> name varchar(20),
-> password varchar(20),
-> primary key(id,name)
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> insert into user2 values(1,"张三","123");
Query OK, 1 row affected (0.01 sec)
mysql> insert into user2 values(2,"张三","123");
Query OK, 1 row affected (0.01 sec)
mysql> insert into user2 values(1,"李四","123");
Query OK, 1 row affected (0.01 sec)
mysql> select * from user2;
+----+------+----------+
| id | name | password |
+----+------+----------+
| 1 | 张三 | 123 |
| 1 | 李四 | 123 |
| 2 | 张三 | 123 |
+----+------+----------+
3 rows in set (0.00 sec)
mysql> describe user2;
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(20) | NO | PRI | NULL | |
| password | varchar(20) | YES | | NULL | |
+----------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
14.2自增约束
mysql> create table user3(
-> id int primary key auto_increment,
-> name varchar(20)
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> insert into user3 (name) values("张三");
Query OK, 1 row affected (0.01 sec)
mysql> select * from user3;
+----+------+
| id | name |
+----+------+
| 1 | 张三 |
+----+------+
1 row in set (0.00 sec)
mysql> insert into user3 (name) values("张三");
Query OK, 1 row affected (0.01 sec)
mysql> select * from user3;
+----+------+
| id | name |
+----+------+
| 1 | 张三 |
| 2 | 张三 |
+----+------+
2 rows in set (0.00 sec)
14.3创建表的时候忘记创建主键约束怎么办
修改表结构,添加主键
mysql> create table user4(
-> id int,
-> name varchar(20)
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> alter table user4 add primary key(id);
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc user4;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
删除主键约束
mysql> alter table user4 drop primary key;
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc user4;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | | NULL | |
| name | varchar(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
使用modify修改字段,添加约束
mysql> alter table user4 modify id int primary key;
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc user4;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
14.2唯一约束
约束修饰字段的值不可以重复
mysql> create table user5(
-> id int,
-> name varchar(20)
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> alter table user5 add unique(name);
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc user5;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(20) | YES | UNI | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> insert into user5 value(1,"张三");
Query OK, 1 row affected (0.01 sec)
mysql> insert into user5 value(1,"张三");
ERROR 1062 (23000): Duplicate entry '张三' for key 'name'
mysql> insert into user5 value(1,"李四");
Query OK, 1 row affected (0.01 sec)
也可以在建表的时候添加约束
mysql> create table user6(
-> id int,
-> name varchar(20),
-> unique(name)
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> desc user6;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(20) | YES | UNI | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
删除唯一约束
mysql> alter table user6 drop index name;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc user6;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
添加约束
mysql> alter table user6 modify name varchar(20) unique;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc user6;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(20) | YES | UNI | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
14.3非空约束
修饰的字段不能为空值
mysql> create table user7(
-> id int,
-> name varchar(20) not null
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> desc user7;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(20) | NO | | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
14.4默认约束
mysql> create table user8(
-> id int,
-> name varchar(20),
-> age int default 10
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> desc user8;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| age | int(11) | YES | | 10 | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
mysql> insert into user8(id,name) values(1,"张三");
Query OK, 1 row affected (0.01 sec)
mysql> select * from user8;
+------+------+------+
| id | name | age |
+------+------+------+
| 1 | 张三 | 10 |
+------+------+------+
1 row in set (0.00 sec)
mysql> insert into user8 values(1,"李四",19);
Query OK, 1 row affected (0.01 sec)
mysql> select * from user8;
+------+------+------+
| id | name | age |
+------+------+------+
| 1 | 张三 | 10 |
| 1 | 李四 | 19 |
+------+------+------+
2 rows in set (0.00 sec)
14.5外键约束
涉及到两个表,父表和子表
–班级表
mysql> create table classes(
-> id int primary key,
-> name varchar(20)
-> );
Query OK, 0 rows affected (0.02 sec)
–学生表
mysql> create table students(
-> id int primary key,
-> name varchar(20),
-> class_id int,
-> foreign key(class_id) references classes(id)
-> );
Query OK, 0 rows affected (0.02 sec)
往班级表插入数据
mysql> insert into classes values(1,"一班");
Query OK, 1 row affected (0.01 sec)
mysql> insert into classes values(2,"二班");
Query OK, 1 row affected (0.01 sec)
mysql> insert into classes values(3,"三班");
Query OK, 1 row affected (0.01 sec)
mysql> insert into classes values(4,"四班");
Query OK, 1 row affected (0.01 sec)
mysql> select * from classes;
+----+------+
| id | name |
+----+------+
| 1 | 一班 |
| 2 | 二班 |
| 3 | 三班 |
| 4 | 四班 |
+----+------+
4 rows in set (0.00 sec)
往学生表中插入数据
mysql> insert into students values(1001,"张三",1);
Query OK, 1 row affected (0.00 sec)
mysql> insert into students values(1002,"李四",2);
Query OK, 1 row affected (0.01 sec)
mysql> insert into students values(1003,"赵武",4);
Query OK, 1 row affected (0.01 sec)
mysql> insert into students values(1004,"甄姬",3);
Query OK, 1 row affected (0.01 sec)
mysql> insert into students values(1005,"廉颇",2);
Query OK, 1 row affected (0.01 sec)
试一下插入class_id = 5的数据
mysql> insert into students values(1006,"小明",5);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test1`.`students`, CONSTRAINT `students_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `classes` (`id`))
可以发现:
①主表classes中没有的的数据值,副表中是不可以使用的;
②主表中的记录被副表引用的情况下不能被删除.
mysql> delete from classes where id=4;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test1`.`students`, CONSTRAINT `students_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `classes` (`id`))
15.数据库的三大设计范式
15.1第一范式:数据表中的所有字段都是不可分割的原子值
mysql> create table student1(
-> id int primary key,
-> name varchar(20),
-> address varchar(30)
-> );
mysql> insert into student1 values(1,"诺克","英雄联盟诺克萨斯");
Query OK, 1 row affected (0.01 sec)
mysql> insert into student1 values(2,"盖伦","英雄联盟德玛西亚");
Query OK, 1 row affected (0.01 sec)
mysql> insert into student1 values(3,"后裔","王者荣耀不知名大陆");
Query OK, 1 row affected (0.01 sec)
mysql> select * from student1;
+----+------+--------------------+
| id | name | address |
+----+------+--------------------+
| 1 | 诺克 | 英雄联盟诺克萨斯 |
| 2 | 盖伦 | 英雄联盟德玛西亚 |
| 3 | 后裔 | 王者荣耀不知名大陆 |
+----+------+--------------------+
3 rows in set (0.00 sec)
字段值还可以继续拆分,就不满足第一范式
mysql> create table student2(
-> id int primary key,
-> name varchar(20),
-> game varchar(10),
-> mainland varchar(10)
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> insert into student2 values(1,"诺克","英雄联盟","诺克萨斯");
Query OK, 1 row affected (0.01 sec)
mysql> insert into student2 values(2,"盖伦","英雄联盟","德玛西亚");
Query OK, 1 row affected (0.01 sec)
mysql> insert into student2 values(3,"后裔","王者荣耀","不知名大陆");
Query OK, 1 row affected (0.01 sec)
mysql> select * from student2;
+----+------+----------+------------+
| id | name | game | mainland |
+----+------+----------+------------+
| 1 | 诺克 | 英雄联盟 | 诺克萨斯 |
| 2 | 盖伦 | 英雄联盟 | 德玛西亚 |
| 3 | 后裔 | 王者荣耀 | 不知名大陆 |
+----+------+----------+------------+
3 rows in set (0.00 sec)
范式的设计越详细,对于某些实际操作可能更好,但不一定都是好处,比如地址分的太详细在取数的时候还要拼接操作,具体设计还要根据具体业务来定.
15.2 第二范式
必须是满足第一范式前提下,第二范式要求,除主键外的每一列都必须完全依赖于主键,如果要出现不完全依赖,只可能发生在联合主键的情况下
例:设计一个订单表
mysql> create table myorder(
-> product_id int,
-> customer_id int,
-> product_name varchar(20),
-> customer_name varchar(20),
-> primary key(product_id,customer_id)
-> );
Query OK, 0 rows affected (0.04 sec)
拆分成如下三张表之后才满足第二范式
mysql> create table myorder(
-> order_id int primary key,
-> product_id int,
-> customer_id int
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> create table product(
-> id int primary key,
-> name varchar(20)
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> create table customer(
-> id int primary key,
-> name varchar(20)
-> );
Query OK, 0 rows affected (0.02 sec)
15.3第三范式
必须先满足第二范式,除开主键列的其他列之间不能有传递依赖的关系
mysql> create table myorder(
-> order_id int primary key,
-> product_id int,
-> customer_id int,
-> customer_phone int#这样的设计phone是依赖于customer_id的,不符合第三范式
-> );
Query OK, 0 rows affected (0.02 sec)
将phone字段添加到customer表中才符合第三范式
mysql> create table customer(
-> id int primary key,
-> name varchar(20),
-> phone int
-> );
16.查询练习
先单独创建一个用于练习的数据库
mysql> create database Stutest;
Query OK, 1 row affected (0.01 sec)
mysql> use Stutest;
Database changed
学生表(Student)
字段:学号,姓名,性别,出生年月日,所在班级
mysql> create table Student(
-> snum varchar(20) primary key,
-> sname varchar(20) not null,
-> ssex varchar(10) not null,
-> sbirthday datetime,
-> class varchar(10)
-> );
Query OK, 0 rows affected (0.02 sec)
教师表(Teacher)
字段:教师编号,教师名字,教师性别,出生年月日,职称,所在部门
mysql> create table teacher(
-> tnu varchar(20) primary key,
-> tname varchar(20) not null,
-> tsex varchar(10) not null,
-> tbirthday datetime,
-> prof varchar(20) not null,
-> depart varchar(20) not null
-> );
Query OK, 0 rows affected (0.02 sec)
课程表(Course)
字段:课程号,课程名称,教师编号
mysql> create table course(
-> cnu varchar(20) primary key,
-> cname varchar(20) not null,
-> tnu varchar(20) not null,
-> foreign key(tnu) references teacher(tnu)
-> );
Query OK, 0 rows affected (0.02 sec)
成绩表(Score)
字段:学号,课程号,成绩
mysql> create table score(
-> sno varchar(20),
-> cno varchar(20),
-> degree decimal,
-> foreign key(sno) references student(snum),
-> foreign key(cno) references course(cnu),
-> primary key(sno,cno)
-> );
Query OK, 0 rows affected (0.02 sec
mysql> show tables;
+-------------------+
| Tables_in_stutest |
+-------------------+
| course |
| score |
| student |
| teacher |
+-------------------+
4 rows in set (0.01 sec)
往数据表中添加数据(此处不一一展示)
insert into student values("101","廉颇","男","1977-09-01","95033");
Query OK, 1 row affected (0.01 sec)
mysql> select * from student;
+------+----------+------+---------------------+-------+
| snum | sname | ssex | sbirthday | class |
+------+----------+------+---------------------+-------+
| 101 | 廉颇 | 男 | 1977-09-01 00:00:00 | 95033 |
| 102 | 张飞 | 男 | 1979-09-01 00:00:00 | 95033 |
| 103 | 晁盖 | 男 | 1970-09-01 00:00:00 | 95033 |
| 104 | 赵云 | 男 | 1980-09-01 00:00:00 | 95033 |
| 105 | 貂蝉 | 女 | 1994-09-01 00:00:00 | 95031 |
| 106 | 诸葛亮 | 男 | 1977-09-01 00:00:00 | 95031 |
| 107 | 金莲 | 女 | 1997-09-01 00:00:00 | 95031 |
| 108 | 镇关西 | 男 | 1967-09-01 00:00:00 | 95031 |
| 109 | 吴下阿蒙 | 男 | 1987-09-01 00:00:00 | 95031 |
+------+----------+------+---------------------+-------+
9 rows in set (0.01 sec)
mysql> insert into teacher values("804","曹操","男","1958-12-02","教授","历史系");
Query OK, 1 row affected (0.01 sec)
mysql> insert into teacher values("856","刘备","男","1968-12-12","副教授","工程系");
Query OK, 1 row affected (0.01 sec)
mysql> insert into teacher values("825","咪蒙","女","1998-12-12","讲师","心理系");
Query OK, 1 row affected (0.01 sec)
mysql> insert into teacher values("831","高圆圆","女","1998-02-22","讲师","心理系");
Query OK, 1 row affected (0.01 sec)
mysql> select * from teacher;
+-----+--------+------+---------------------+--------+--------+
| tnu | tname | tsex | tbirthday | prof | depart |
+-----+--------+------+---------------------+--------+--------+
| 804 | 曹操 | 男 | 1958-12-02 00:00:00 | 教授 | 历史系 |
| 825 | 咪蒙 | 女 | 1998-12-12 00:00:00 | 讲师 | 心理系 |
| 831 | 高圆圆 | 女 | 1998-02-22 00:00:00 | 讲师 | 心理系 |
| 856 | 刘备 | 男 | 1968-12-12 00:00:00 | 副教授 | 工程系 |
+-----+--------+------+---------------------+--------+--------+
4 rows in set (0.00 sec)
mysql> insert into course values("3-105","心理学教育","825");
Query OK, 1 row affected (0.01 sec)
mysql> insert into course values("3-245","孙子兵法","804");
Query OK, 1 row affected (0.01 sec)
mysql> insert into course values("6-166","运筹学","856");
Query OK, 1 row affected (0.01 sec)
mysql> insert into course values("9-888","演员的自我修养","831");
Query OK, 1 row affected (0.01 sec)
mysql> select * from course;
+-------+----------------+-----+
| cnu | cname | tnu |
+-------+----------------+-----+
| 3-105 | 心理学教育 | 825 |
| 3-245 | 孙子兵法 | 804 |
| 6-166 | 运筹学 | 856 |
| 9-888 | 演员的自我修养 | 831 |
+-------+----------------+-----+
4 rows in set (0.00 sec)
mysql> insert into score values("109","6-166","81");
Query OK, 1 row affected (0.01 sec)
mysql> select * from score;
+-----+-------+--------+
| sno | cno | degree |
+-----+-------+--------+
| 103 | 3-105 | 92 |
| 103 | 3-245 | 86 |
| 103 | 6-166 | 85 |
| 105 | 3-105 | 88 |
| 105 | 3-245 | 75 |
| 105 | 6-166 | 79 |
| 109 | 3-105 | 76 |
| 109 | 3-245 | 68 |
| 109 | 6-166 | 81 |
+-----+-------+--------+
9 rows in set (0.00 sec)
查询练习题
1.查询student表中的所有记录
mysql> select * from student;
+------+----------+------+---------------------+-------+
| snum | sname | ssex | sbirthday | class |
+------+----------+------+---------------------+-------+
| 101 | 廉颇 | 男 | 1977-09-01 00:00:00 | 95033 |
| 102 | 张飞 | 男 | 1979-09-01 00:00:00 | 95033 |
| 103 | 晁盖 | 男 | 1970-09-01 00:00:00 | 95033 |
| 104 | 赵云 | 男 | 1980-09-01 00:00:00 | 95033 |
| 105 | 貂蝉 | 女 | 1994-09-01 00:00:00 | 95031 |
| 106 | 诸葛亮 | 男 | 1977-09-01 00:00:00 | 95031 |
| 107 | 金莲 | 女 | 1997-09-01 00:00:00 | 95031 |
| 108 | 镇关西 | 男 | 1967-09-01 00:00:00 | 95031 |
| 109 | 吴下阿蒙 | 男 | 1987-09-01 00:00:00 | 95031 |
+------+----------+------+---------------------+-------+
9 rows in set (0.00 sec)
2.查询student表中所有记录的sname,ssex和class列
mysql> select sname,ssex,class from student;
+----------+------+-------+
| sname | ssex | class |
+----------+------+-------+
| 廉颇 | 男 | 95033 |
| 张飞 | 男 | 95033 |
| 晁盖 | 男 | 95033 |
| 赵云 | 男 | 95033 |
| 貂蝉 | 女 | 95031 |
| 诸葛亮 | 男 | 95031 |
| 金莲 | 女 | 95031 |
| 镇关西 | 男 | 95031 |
| 吴下阿蒙 | 男 | 95031 |
+----------+------+-------+
9 rows in set (0.01 sec)
3.查询教师表中不重复的depart列
mysql> select * from teacher;
+-----+--------+------+---------------------+--------+--------+
| tnu | tname | tsex | tbirthday | prof | depart |
+-----+--------+------+---------------------+--------+--------+
| 804 | 曹操 | 男 | 1958-12-02 00:00:00 | 教授 | 历史系 |
| 825 | 咪蒙 | 女 | 1998-12-12 00:00:00 | 讲师 | 心理系 |
| 831 | 高圆圆 | 女 | 1998-02-22 00:00:00 | 讲师 | 心理系 |
| 856 | 刘备 | 男 | 1968-12-12 00:00:00 | 副教授 | 工程系 |
+-----+--------+------+---------------------+--------+--------+
4 rows in set (0.00 sec)
mysql> select distinct depart from teacher;
+--------+
| depart |
+--------+
| 历史系 |
| 心理系 |
| 工程系 |
+--------+
3 rows in set (0.01 sec)
4.查询score表中成绩在60-80之间的所有记录
查询区间between…and…
mysql> select * from score where degree between 60 and 80;
+-----+-------+--------+
| sno | cno | degree |
+-----+-------+--------+
| 105 | 3-245 | 75 |
| 105 | 6-166 | 79 |
| 109 | 3-105 | 76 |
| 109 | 3-245 | 68 |
+-----+-------+--------+
4 rows in set (0.01 sec)
或者直接使用运算符比较
mysql> select * from score where degree>60 and degree<80;
+-----+-------+--------+
| sno | cno | degree |
+-----+-------+--------+
| 105 | 3-245 | 75 |
| 105 | 6-166 | 79 |
| 109 | 3-105 | 76 |
| 109 | 3-245 | 68 |
+-----+-------+--------+
4 rows in set (0.01 sec)
5.查询score表中成绩为85,86或88的记录
mysql> select * from score where degree in(85,86,88)
-> ;
+-----+-------+--------+
| sno | cno | degree |
+-----+-------+--------+
| 103 | 3-245 | 86 |
| 103 | 6-166 | 85 |
| 105 | 3-105 | 88 |
+-----+-------+--------+
3 rows in set (0.01 sec)
6.查询student表中"95031"班或性别为"女"的同学记录
mysql> select * from student where class="95031" or ssex="女";
+------+----------+------+---------------------+-------+
| snum | sname | ssex | sbirthday | class |
+------+----------+------+---------------------+-------+
| 105 | 貂蝉 | 女 | 1994-09-01 00:00:00 | 95031 |
| 106 | 诸葛亮 | 男 | 1977-09-01 00:00:00 | 95031 |
| 107 | 金莲 | 女 | 1997-09-01 00:00:00 | 95031 |
| 108 | 镇关西 | 男 | 1967-09-01 00:00:00 | 95031 |
| 109 | 吴下阿蒙 | 男 | 1987-09-01 00:00:00 | 95031 |
+------+----------+------+---------------------+-------+
5 rows in set (0.00 sec)
7.以class降序查询student表的所有记录
mysql> select * from student order by class desc;
+------+----------+------+---------------------+-------+
| snum | sname | ssex | sbirthday | class |
+------+----------+------+---------------------+-------+
| 101 | 廉颇 | 男 | 1977-09-01 00:00:00 | 95033 |
| 102 | 张飞 | 男 | 1979-09-01 00:00:00 | 95033 |
| 103 | 晁盖 | 男 | 1970-09-01 00:00:00 | 95033 |
| 104 | 赵云 | 男 | 1980-09-01 00:00:00 | 95033 |
| 105 | 貂蝉 | 女 | 1994-09-01 00:00:00 | 95031 |
| 106 | 诸葛亮 | 男 | 1977-09-01 00:00:00 | 95031 |
| 107 | 金莲 | 女 | 1997-09-01 00:00:00 | 95031 |
| 108 | 镇关西 | 男 | 1967-09-01 00:00:00 | 95031 |
| 109 | 吴下阿蒙 | 男 | 1987-09-01 00:00:00 | 95031 |
+------+----------+------+---------------------+-------+
9 rows in set (0.01 sec)
#asc默认升序
mysql> select * from student order by class;
+------+----------+------+---------------------+-------+
| snum | sname | ssex | sbirthday | class |
+------+----------+------+---------------------+-------+
| 105 | 貂蝉 | 女 | 1994-09-01 00:00:00 | 95031 |
| 106 | 诸葛亮 | 男 | 1977-09-01 00:00:00 | 95031 |
| 107 | 金莲 | 女 | 1997-09-01 00:00:00 | 95031 |
| 108 | 镇关西 | 男 | 1967-09-01 00:00:00 | 95031 |
| 109 | 吴下阿蒙 | 男 | 1987-09-01 00:00:00 | 95031 |
| 101 | 廉颇 | 男 | 1977-09-01 00:00:00 | 95033 |
| 102 | 张飞 | 男 | 1979-09-01 00:00:00 | 95033 |
| 103 | 晁盖 | 男 | 1970-09-01 00:00:00 | 95033 |
| 104 | 赵云 | 男 | 1980-09-01 00:00:00 | 95033 |
+------+----------+------+---------------------+-------+
9 rows in set (0.00 sec)
8.以cno升序,degree降序查询score表的所有记录
mysql> select * from score order by cno asc,degree desc;
+-----+-------+--------+
| sno | cno | degree |
+-----+-------+--------+
| 103 | 3-105 | 92 |
| 105 | 3-105 | 88 |
| 109 | 3-105 | 76 |
| 103 | 3-245 | 86 |
| 105 | 3-245 | 75 |
| 109 | 3-245 | 68 |
| 103 | 6-166 | 85 |
| 109 | 6-166 | 81 |
| 105 | 6-166 | 79 |
+-----+-------+--------+
9 rows in set (0.00 sec)
9.查询"95031"班的学生人数
mysql> select count(*) from student where class="95031";
+----------+
| count(*) |
+----------+
| 5 |
+----------+
1 row in set (0.01 sec)
10.查询score表中的最高分的学生的学生学号和课程号(子查询或者排序)
子查询
mysql> select sno,cno from score where degree=(select max(degree) from score);
+-----+-------+
| sno | cno |
+-----+-------+
| 103 | 3-105 |
+-----+-------+
1 row in set (0.00 sec)
排序(用排序查询的时候如果存在两个最高分会出现问题)
mysql> select * from score order by degree;
+-----+-------+--------+
| sno | cno | degree |
+-----+-------+--------+
| 109 | 3-245 | 68 |
| 105 | 3-245 | 75 |
| 109 | 3-105 | 76 |
| 105 | 6-166 | 79 |
| 109 | 6-166 | 81 |
| 103 | 6-166 | 85 |
| 103 | 3-245 | 86 |
| 105 | 3-105 | 88 |
| 103 | 3-105 | 92 |
+-----+-------+--------+
9 rows in set (0.00 sec)
mysql> select * from score order by degree desc limit 0,1;
+-----+-------+--------+
| sno | cno | degree |
+-----+-------+--------+
| 103 | 3-105 | 92 |
+-----+-------+--------+
1 row in set (0.01 sec)
limit表示第一个数字从多少开始.第二个数字表示查多少条
mysql> select * from score order by degree desc limit 2,3;
+-----+-------+--------+
| sno | cno | degree |
+-----+-------+--------+
| 103 | 3-245 | 86 |
| 103 | 6-166 | 85 |
| 109 | 6-166 | 81 |
+-----+-------+--------+
3 rows in set (0.00 sec)
11.查询每门课的平均成绩
mysql> select * from course;
+-------+----------------+-----+
| cnu | cname | tnu |
+-------+----------------+-----+
| 3-105 | 心理学教育 | 825 |
| 3-245 | 孙子兵法 | 804 |
| 6-166 | 运筹学 | 856 |
| 9-888 | 演员的自我修养 | 831 |
+-------+----------------+-----+
4 rows in set (0.01 sec)
mysql> select avg(degree) from score where cno="3-105";
+-------------+
| avg(degree) |
+-------------+
| 85.3333 |
+-------------+
1 row in set (0.01 sec)
在一个sql语句中查询每门课的平均成绩
mysql> select cno,avg(degree) from score group by cno;
+-------+-------------+
| cno | avg(degree) |
+-------+-------------+
| 3-105 | 85.3333 |
| 3-245 | 76.3333 |
| 6-166 | 81.6667 |
+-------+-------------+
3 rows in set (0.01 sec)
12.查询score表中至少有两名学生选修的并以3开头的课程的平均分数
group by 后面跟条件需要用having
mysql> select * from score;
+-----+-------+--------+
| sno | cno | degree |
+-----+-------+--------+
| 103 | 3-105 | 92 |
| 103 | 3-245 | 86 |
| 103 | 6-166 | 85 |
| 105 | 3-105 | 88 |
| 105 | 3-245 | 75 |
| 105 | 6-166 | 79 |
| 109 | 3-105 | 76 |
| 109 | 3-245 | 68 |
| 109 | 6-166 | 81 |
+-----+-------+--------+
9 rows in set (0.00 sec)
mysql> select cno,avg(degree) from score group by cno having count(cno)>1 and cno like "3%";
+-------+-------------+
| cno | avg(degree) |
+-------+-------------+
| 3-105 | 85.3333 |
| 3-245 | 76.3333 |
+-------+-------------+
2 rows in set (0.00 sec)
mysql> select cno,avg(degree),count(cno) from score group by cno having count(cno)>1 and cno like "3%";
+-------+-------------+------------+
| cno | avg(degree) | count(cno) |
+-------+-------------+------------+
| 3-105 | 85.3333 | 3 |
| 3-245 | 76.3333 | 3 |
+-------+-------------+------------+
2 rows in set (0.00 sec)
13.查询分数大于70,小于90的sno列
mysql> select sno,degree from score where degree>70 and degree<90;
+-----+--------+
| sno | degree |
+-----+--------+
| 103 | 86 |
| 103 | 85 |
| 105 | 88 |
| 105 | 75 |
| 105 | 79 |
| 109 | 76 |
| 109 | 81 |
+-----+--------+
7 rows in set (0.01 sec)
mysql> select sno,degree from score where degree between 70 and 90;
+-----+--------+
| sno | degree |
+-----+--------+
| 103 | 86 |
| 103 | 85 |
| 105 | 88 |
| 105 | 75 |
| 105 | 79 |
| 109 | 76 |
| 109 | 81 |
+-----+--------+
7 rows in set (0.00 sec)
14.查询所有学生的sname,cno和degree列
mysql> select sname,cno,degree from student,score where student.snum=score.sno;
+----------+-------+--------+
| sname | cno | degree |
+----------+-------+--------+
| 晁盖 | 3-105 | 92 |
| 晁盖 | 3-245 | 86 |
| 晁盖 | 6-166 | 85 |
| 貂蝉 | 3-105 | 88 |
| 貂蝉 | 3-245 | 75 |
| 貂蝉 | 6-166 | 79 |
| 吴下阿蒙 | 3-105 | 76 |
| 吴下阿蒙 | 3-245 | 68 |
| 吴下阿蒙 | 6-166 | 81 |
+----------+-------+--------+
9 rows in set (0.01 sec)
15查询所有学生的sno,cname和degree列
mysql> select sno,cname,degree from course,score where course.cnu=score.cno;
+-----+------------+--------+
| sno | cname | degree |
+-----+------------+--------+
| 103 | 心理学教育 | 92 |
| 103 | 孙子兵法 | 86 |
| 103 | 运筹学 | 85 |
| 105 | 心理学教育 | 88 |
| 105 | 孙子兵法 | 75 |
| 105 | 运筹学 | 79 |
| 109 | 心理学教育 | 76 |
| 109 | 孙子兵法 | 68 |
| 109 | 运筹学 | 81 |
+-----+------------+--------+
9 rows in set (0.00 sec)
16.查询所有学生的sname,cname和degree列
mysql> select sname,cname,degree from student,course,score
-> where student.snum=score.sno and course.cnu=score.cno;
+----------+------------+--------+
| sname | cname | degree |
+----------+------------+--------+
| 晁盖 | 心理学教育 | 92 |
| 晁盖 | 孙子兵法 | 86 |
| 晁盖 | 运筹学 | 85 |
| 貂蝉 | 心理学教育 | 88 |
| 貂蝉 | 孙子兵法 | 75 |
| 貂蝉 | 运筹学 | 79 |
| 吴下阿蒙 | 心理学教育 | 76 |
| 吴下阿蒙 | 孙子兵法 | 68 |
| 吴下阿蒙 | 运筹学 | 81 |
+----------+------------+--------+
9 rows in set (0.01 sec)
mysql> select sname,cname,degree,student.snum,course.cnu from student,course,score
-> where student.snum=score.sno and course.cnu=score.cno;
+----------+------------+--------+------+-------+
| sname | cname | degree | snum | cnu |
+----------+------------+--------+------+-------+
| 晁盖 | 心理学教育 | 92 | 103 | 3-105 |
| 晁盖 | 孙子兵法 | 86 | 103 | 3-245 |
| 晁盖 | 运筹学 | 85 | 103 | 6-166 |
| 貂蝉 | 心理学教育 | 88 | 105 | 3-105 |
| 貂蝉 | 孙子兵法 | 75 | 105 | 3-245 |
| 貂蝉 | 运筹学 | 79 | 105 | 6-166 |
| 吴下阿蒙 | 心理学教育 | 76 | 109 | 3-105 |
| 吴下阿蒙 | 孙子兵法 | 68 | 109 | 3-245 |
| 吴下阿蒙 | 运筹学 | 81 | 109 | 6-166 |
+----------+------------+--------+------+-------+
9 rows in set (0.00 sec)
mysql> select sname,cname,degree,student.snum as stu_snum,course.cnu as cou_cnu from student,course,score
-> where student.snum=score.sno and course.cnu=score.cno;
+----------+------------+--------+----------+---------+
| sname | cname | degree | stu_snum | cou_cnu |
+----------+------------+--------+----------+---------+
| 晁盖 | 心理学教育 | 92 | 103 | 3-105 |
| 晁盖 | 孙子兵法 | 86 | 103 | 3-245 |
| 晁盖 | 运筹学 | 85 | 103 | 6-166 |
| 貂蝉 | 心理学教育 | 88 | 105 | 3-105 |
| 貂蝉 | 孙子兵法 | 75 | 105 | 3-245 |
| 貂蝉 | 运筹学 | 79 | 105 | 6-166 |
| 吴下阿蒙 | 心理学教育 | 76 | 109 | 3-105 |
| 吴下阿蒙 | 孙子兵法 | 68 | 109 | 3-245 |
| 吴下阿蒙 | 运筹学 | 81 | 109 | 6-166 |
+----------+------------+--------+----------+---------+
9 rows in set (0.01 sec)
17.查询"95031"班学生每门课的平均分
mysql> select * from student where class="95031";
+------+----------+------+---------------------+-------+
| snum | sname | ssex | sbirthday | class |
+------+----------+------+---------------------+-------+
| 105 | 貂蝉 | 女 | 1994-09-01 00:00:00 | 95031 |
| 106 | 诸葛亮 | 男 | 1977-09-01 00:00:00 | 95031 |
| 107 | 金莲 | 女 | 1997-09-01 00:00:00 | 95031 |
| 108 | 镇关西 | 男 | 1967-09-01 00:00:00 | 95031 |
| 109 | 吴下阿蒙 | 男 | 1987-09-01 00:00:00 | 95031 |
+------+----------+------+---------------------+-------+
5 rows in set (0.03 sec)
mysql> select * from score where sno in (select snum from student where class="95031");
+-----+-------+--------+
| sno | cno | degree |
+-----+-------+--------+
| 105 | 3-105 | 88 |
| 105 | 3-245 | 75 |
| 105 | 6-166 | 79 |
| 109 | 3-105 | 76 |
| 109 | 3-245 | 68 |
| 109 | 6-166 | 81 |
+-----+-------+--------+
6 rows in set (0.01 sec)
mysql> select cno,avg(degree)
-> from score
-> where sno in (select snum from student where class="95031")
-> group by cno;
+-------+-------------+
| cno | avg(degree) |
+-------+-------------+
| 3-105 | 82.0000 |
| 3-245 | 71.5000 |
| 6-166 | 80.0000 |
+-------+-------------+
3 rows in set (0.01 sec)
18.查询选修"3-105"课程的成绩高于"109"号同学"3-105"的成绩的所有同学记录
mysql> select * from score where cno="3-105" and degree>(select degree from score where sno="109" and cno="3-105");
+-----+-------+--------+
| sno | cno | degree |
+-----+-------+--------+
| 103 | 3-105 | 92 |
| 105 | 3-105 | 88 |
+-----+-------+--------+
2 rows in set (0.01 sec)
19.查询成绩高于学号为"109",课程号为"3-105"的成绩的所有记录
mysql> select * from score where degree>(select degree from score where sno="109" and cno="3-105");
+-----+-------+--------+
| sno | cno | degree |
+-----+-------+--------+
| 103 | 3-105 | 92 |
| 103 | 3-245 | 86 |
| 103 | 6-166 | 85 |
| 105 | 3-105 | 88 |
| 105 | 6-166 | 79 |
| 109 | 6-166 | 81 |
+-----+-------+--------+
6 rows in set (0.02 sec)
20.查询和学号为108、101的同学同年出生的snum,sname和sbirthday列
mysql> select * from student where snum in (108,101);
+------+--------+------+---------------------+-------+
| snum | sname | ssex | sbirthday | class |
+------+--------+------+---------------------+-------+
| 101 | 廉颇 | 男 | 1977-09-01 00:00:00 | 95033 |
| 108 | 镇关西 | 男 | 1967-09-01 00:00:00 | 95031 |
+------+--------+------+---------------------+-------+
2 rows in set (0.01 sec)
mysql> select year(sbirthday) from student where snum in (108,101);
+-----------------+
| year(sbirthday) |
+-----------------+
| 1977 |
| 1967 |
+-----------------+
2 rows in set (0.01 sec)
mysql> select * from student where year(sbirthday) in (select year(sbirthday) from student where snum in (108,101));
+------+--------+------+---------------------+-------+
| snum | sname | ssex | sbirthday | class |
+------+--------+------+---------------------+-------+
| 101 | 廉颇 | 男 | 1977-09-01 00:00:00 | 95033 |
| 106 | 诸葛亮 | 男 | 1977-09-01 00:00:00 | 95031 |
| 108 | 镇关西 | 男 | 1967-09-01 00:00:00 | 95031 |
+------+--------+------+---------------------+-------+
3 rows in set (0.01 sec)
21.查询"咪蒙"教师任课的学生成绩
mysql> select tnu from teacher where tname="咪蒙";
+-----+
| tnu |
+-----+
| 825 |
+-----+
1 row in set (0.00 sec)
mysql> select cnu from course where tnu=(select tnu from teacher where tname="咪蒙");
+-------+
| cnu |
+-------+
| 3-105 |
+-------+
1 row in set (0.00 sec)
mysql> select * from score where cno=(select cnu from course where tnu=(select tnu from teacher where tname="咪蒙"));
+-----+-------+--------+
| sno | cno | degree |
+-----+-------+--------+
| 103 | 3-105 | 92 |
| 105 | 3-105 | 88 |
| 109 | 3-105 | 76 |
+-----+-------+--------+
3 rows in set (0.00 sec)
22.查询选修某课程的同学人数多于5人的教师姓名
mysql> insert into score values("101","3-105",90);
Query OK, 1 row affected (0.01 sec)
mysql> insert into score values("102","3-105","91");
Query OK, 1 row affected (0.01 sec)
mysql> insert into score values("104","3-105",89);
Query OK, 1 row affected (0.01 sec)
mysql> select * from score order by cno;
+-----+-------+--------+
| sno | cno | degree |
+-----+-------+--------+
| 101 | 3-105 | 90 |
| 102 | 3-105 | 91 |
| 103 | 3-105 | 92 |
| 104 | 3-105 | 89 |
| 105 | 3-105 | 88 |
| 109 | 3-105 | 76 |
| 103 | 3-245 | 86 |
| 105 | 3-245 | 75 |
| 109 | 3-245 | 68 |
| 103 | 6-166 | 85 |
| 105 | 6-166 | 79 |
| 109 | 6-166 | 81 |
+-----+-------+--------+
12 rows in set (0.00 sec)
mysql> select cno from score group by cno having count(*)>5;
+-------+
| cno |
+-------+
| 3-105 |
+-------+
1 row in set (0.01 sec)
mysql> select tnu from course where cnu=(select cno from score group by cno having count(*)>5);
+-----+
| tnu |
+-----+
| 825 |
+-----+
1 row in set (0.00 sec)
mysql> select * from teacher where tnu=(select tnu from course where cnu=(select cno from score group by cno having count(*)>5));
+-----+-------+------+---------------------+------+--------+
| tnu | tname | tsex | tbirthday | prof | depart |
+-----+-------+------+---------------------+------+--------+
| 825 | 咪蒙 | 女 | 1998-12-12 00:00:00 | 讲师 | 心理系 |
+-----+-------+------+---------------------+------+--------+
1 row in set (0.00 sec)
23.查询"95033"班与"95031"班全体学生记录
mysql> select * from student where class in ("95031","95033");
+------+----------+------+---------------------+-------+
| snum | sname | ssex | sbirthday | class |
+------+----------+------+---------------------+-------+
| 101 | 廉颇 | 男 | 1977-09-01 00:00:00 | 95033 |
| 102 | 张飞 | 男 | 1979-09-01 00:00:00 | 95033 |
| 103 | 晁盖 | 男 | 1970-09-01 00:00:00 | 95033 |
| 104 | 赵云 | 男 | 1980-09-01 00:00:00 | 95033 |
| 105 | 貂蝉 | 女 | 1994-09-01 00:00:00 | 95031 |
| 106 | 诸葛亮 | 男 | 1977-09-01 00:00:00 | 95031 |
| 107 | 金莲 | 女 | 1997-09-01 00:00:00 | 95031 |
| 108 | 镇关西 | 男 | 1967-09-01 00:00:00 | 95031 |
| 109 | 吴下阿蒙 | 男 | 1987-09-01 00:00:00 | 95031 |
+------+----------+------+---------------------+-------+
9 rows in set (0.01 sec)
24.查询存在有85分以上成绩的课程cno
mysql> select cno,degree from score where degree>85;
+-------+--------+
| cno | degree |
+-------+--------+
| 3-105 | 90 |
| 3-105 | 91 |
| 3-105 | 92 |
| 3-245 | 86 |
| 3-105 | 89 |
| 3-105 | 88 |
+-------+--------+
6 rows in set (0.01 sec)
25.查询"心理系"教师所教课程的成绩表
mysql> select * from teacher where depart="心理系";
+-----+--------+------+---------------------+------+--------+
| tnu | tname | tsex | tbirthday | prof | depart |
+-----+--------+------+---------------------+------+--------+
| 825 | 咪蒙 | 女 | 1998-12-12 00:00:00 | 讲师 | 心理系 |
| 831 | 高圆圆 | 女 | 1998-02-22 00:00:00 | 讲师 | 心理系 |
+-----+--------+------+---------------------+------+--------+
2 rows in set (0.01 sec)
mysql> select * from course where tnu in (select tnu from teacher where depart="心理系");
+-------+----------------+-----+
| cnu | cname | tnu |
+-------+----------------+-----+
| 3-105 | 心理学教育 | 825 |
| 9-888 | 演员的自我修养 | 831 |
+-------+----------------+-----+
2 rows in set (0.00 sec)
mysql> select * from score where cno in (select cnu from course where tnu in (select tnu from teacher where depart="心理系"));
+-----+-------+--------+
| sno | cno | degree |
+-----+-------+--------+
| 101 | 3-105 | 90 |
| 102 | 3-105 | 91 |
| 103 | 3-105 | 92 |
| 104 | 3-105 | 89 |
| 105 | 3-105 | 88 |
| 109 | 3-105 | 76 |
+-----+-------+--------+
6 rows in set (0.00 sec)
26.查询"计算机系"与"电子工程系"不同职称的tname和prof
mysql> insert into teacher values("911","李冰","男","1988-02-02","副教授","计算机系");
Query OK, 1 row affected (0.01 sec)
mysql> insert into teacher values("912","王平","男","1988-02-02","助教","计算机系");
Query OK, 1 row affected (0.01 sec)
mysql> insert into teacher values("913","秋雅","女","1988-02-03","助教","电子工程系");
Query OK, 1 row affected (0.01 sec)
mysql> insert into teacher values("914","静香","女","1998-02-03","讲师","电子工程系");
Query OK, 1 row affected (0.01 sec)
mysql> select * from teacher;
+-----+--------+------+---------------------+--------+------------+
| tnu | tname | tsex | tbirthday | prof | depart |
+-----+--------+------+---------------------+--------+------------+
| 804 | 曹操 | 男 | 1958-12-02 00:00:00 | 教授 | 历史系 |
| 825 | 咪蒙 | 女 | 1998-12-12 00:00:00 | 讲师 | 心理系 |
| 831 | 高圆圆 | 女 | 1998-02-22 00:00:00 | 讲师 | 心理系 |
| 856 | 刘备 | 男 | 1968-12-12 00:00:00 | 副教授 | 工程系 |
| 911 | 李冰 | 男 | 1988-02-02 00:00:00 | 副教授 | 计算机系 |
| 912 | 王平 | 男 | 1988-02-02 00:00:00 | 助教 | 计算机系 |
| 913 | 秋雅 | 女 | 1988-02-03 00:00:00 | 助教 | 电子工程系 |
| 914 | 静香 | 女 | 1998-02-03 00:00:00 | 讲师 | 电子工程系 |
+-----+--------+------+---------------------+--------+------------+
8 rows in set (0.00 sec)
union作用:求并集
mysql> select * from teacher where depart="计算机系" and prof not in (select prof from teacher where depart="电子工程系")
-> union
-> select * from teacher where depart="电子工程系" and prof not in (select prof from teacher where depart="计算机系");
+-----+-------+------+---------------------+--------+------------+
| tnu | tname | tsex | tbirthday | prof | depart |
+-----+-------+------+---------------------+--------+------------+
| 911 | 李冰 | 男 | 1988-02-02 00:00:00 | 副教授 | 计算机系 |
| 914 | 静香 | 女 | 1998-02-03 00:00:00 | 讲师 | 电子工程系 |
+-----+-------+------+---------------------+--------+------------+
2 rows in set (0.01 sec)
27.查询选修编号为"3-105"课程且成绩至少高于选修编号"3-245"的同学的cno,sno和degree,并按照degree降序排列
mysql> select * from score where cno="3-245";
+-----+-------+--------+
| sno | cno | degree |
+-----+-------+--------+
| 103 | 3-245 | 86 |
| 105 | 3-245 | 75 |
| 109 | 3-245 | 68 |
+-----+-------+--------+
3 rows in set (0.01 sec)
mysql> select * from score where cno="3-105";
+-----+-------+--------+
| sno | cno | degree |
+-----+-------+--------+
| 101 | 3-105 | 90 |
| 102 | 3-105 | 91 |
| 103 | 3-105 | 92 |
| 104 | 3-105 | 89 |
| 105 | 3-105 | 88 |
| 109 | 3-105 | 76 |
+-----+-------+--------+
6 rows in set (0.00 sec)
至少–大于其中至少一个,any
mysql> select * from score
-> where cno="3-105"
-> and degree>any(select degree from score where cno="3-245")
-> order by degree desc;
+-----+-------+--------+
| sno | cno | degree |
+-----+-------+--------+
| 103 | 3-105 | 92 |
| 102 | 3-105 | 91 |
| 101 | 3-105 | 90 |
| 104 | 3-105 | 89 |
| 105 | 3-105 | 88 |
| 109 | 3-105 | 76 |
+-----+-------+--------+
6 rows in set (0.01 sec)
28.查询选修编号为"3-105"且成绩高于选修编号为"3-245"课程的同学的cno,sno和degree
all表示所有的关系
mysql> select * from score
-> where cno="3-105"
-> and degree>all(select degree from score where cno="3-245");
+-----+-------+--------+
| sno | cno | degree |
+-----+-------+--------+
| 101 | 3-105 | 90 |
| 102 | 3-105 | 91 |
| 103 | 3-105 | 92 |
| 104 | 3-105 | 89 |
| 105 | 3-105 | 88 |
+-----+-------+--------+
5 rows in set (0.07 sec)
29.查询所有教师和同学的name、sex和birthday
mysql> select tname,tsex,tbirthday from teacher;
+--------+------+---------------------+
| tname | tsex | tbirthday |
+--------+------+---------------------+
| 曹操 | 男 | 1958-12-02 00:00:00 |
| 咪蒙 | 女 | 1998-12-12 00:00:00 |
| 高圆圆 | 女 | 1998-02-22 00:00:00 |
| 刘备 | 男 | 1968-12-12 00:00:00 |
| 李冰 | 男 | 1988-02-02 00:00:00 |
| 王平 | 男 | 1988-02-02 00:00:00 |
| 秋雅 | 女 | 1988-02-03 00:00:00 |
| 静香 | 女 | 1998-02-03 00:00:00 |
+--------+------+---------------------+
8 rows in set (0.01 sec)
mysql> select sname,ssex,sbirthday from student;
+----------+------+---------------------+
| sname | ssex | sbirthday |
+----------+------+---------------------+
| 廉颇 | 男 | 1977-09-01 00:00:00 |
| 张飞 | 男 | 1979-09-01 00:00:00 |
| 晁盖 | 男 | 1970-09-01 00:00:00 |
| 赵云 | 男 | 1980-09-01 00:00:00 |
| 貂蝉 | 女 | 1994-09-01 00:00:00 |
| 诸葛亮 | 男 | 1977-09-01 00:00:00 |
| 金莲 | 女 | 1997-09-01 00:00:00 |
| 镇关西 | 男 | 1967-09-01 00:00:00 |
| 吴下阿蒙 | 男 | 1987-09-01 00:00:00 |
| 马云 | 男 | 1974-06-03 00:00:00 |
+----------+------+---------------------+
10 rows in set (0.01 sec)
mysql> select tname,tsex,tbirthday from teacher
-> union
-> select sname,ssex,sbirthday from student;
+----------+------+---------------------+
| tname | tsex | tbirthday |
+----------+------+---------------------+
| 曹操 | 男 | 1958-12-02 00:00:00 |
| 咪蒙 | 女 | 1998-12-12 00:00:00 |
| 高圆圆 | 女 | 1998-02-22 00:00:00 |
| 刘备 | 男 | 1968-12-12 00:00:00 |
| 李冰 | 男 | 1988-02-02 00:00:00 |
| 王平 | 男 | 1988-02-02 00:00:00 |
| 秋雅 | 女 | 1988-02-03 00:00:00 |
| 静香 | 女 | 1998-02-03 00:00:00 |
| 廉颇 | 男 | 1977-09-01 00:00:00 |
| 张飞 | 男 | 1979-09-01 00:00:00 |
| 晁盖 | 男 | 1970-09-01 00:00:00 |
| 赵云 | 男 | 1980-09-01 00:00:00 |
| 貂蝉 | 女 | 1994-09-01 00:00:00 |
| 诸葛亮 | 男 | 1977-09-01 00:00:00 |
| 金莲 | 女 | 1997-09-01 00:00:00 |
| 镇关西 | 男 | 1967-09-01 00:00:00 |
| 吴下阿蒙 | 男 | 1987-09-01 00:00:00 |
| 马云 | 男 | 1974-06-03 00:00:00 |
+----------+------+---------------------+
18 rows in set (0.01 sec)
使用union之后,查询的结果虽然合并了,但是字段名称却都是tname,tsex,tbirthday,所以需要自定义字段
使用别名 as
mysql> select tname as name,tsex as sex,tbirthday as birthday from teacher
-> union
-> select sname,ssex,sbirthday from student;
+----------+-----+---------------------+
| name | sex | birthday |
+----------+-----+---------------------+
| 曹操 | 男 | 1958-12-02 00:00:00 |
| 咪蒙 | 女 | 1998-12-12 00:00:00 |
| 高圆圆 | 女 | 1998-02-22 00:00:00 |
| 刘备 | 男 | 1968-12-12 00:00:00 |
| 李冰 | 男 | 1988-02-02 00:00:00 |
| 王平 | 男 | 1988-02-02 00:00:00 |
| 秋雅 | 女 | 1988-02-03 00:00:00 |
| 静香 | 女 | 1998-02-03 00:00:00 |
| 廉颇 | 男 | 1977-09-01 00:00:00 |
| 张飞 | 男 | 1979-09-01 00:00:00 |
| 晁盖 | 男 | 1970-09-01 00:00:00 |
| 赵云 | 男 | 1980-09-01 00:00:00 |
| 貂蝉 | 女 | 1994-09-01 00:00:00 |
| 诸葛亮 | 男 | 1977-09-01 00:00:00 |
| 金莲 | 女 | 1997-09-01 00:00:00 |
| 镇关西 | 男 | 1967-09-01 00:00:00 |
| 吴下阿蒙 | 男 | 1987-09-01 00:00:00 |
| 马云 | 男 | 1974-06-03 00:00:00 |
+----------+-----+---------------------+
18 rows in set (0.01 sec)
30.查询所有女教师和女同学的name、sex和birthday
mysql> select tname as name,tsex as sex,tbirthday as birthday from teacher where tsex="女"
-> union
-> select sname,ssex,sbirthday from student where ssex="女";
+--------+-----+---------------------+
| name | sex | birthday |
+--------+-----+---------------------+
| 咪蒙 | 女 | 1998-12-12 00:00:00 |
| 高圆圆 | 女 | 1998-02-22 00:00:00 |
| 秋雅 | 女 | 1988-02-03 00:00:00 |
| 静香 | 女 | 1998-02-03 00:00:00 |
| 貂蝉 | 女 | 1994-09-01 00:00:00 |
| 金莲 | 女 | 1997-09-01 00:00:00 |
+--------+-----+---------------------+
6 rows in set (0.01 sec)
31.查询成绩比该课程平均成绩低的同学的成绩表
mysql> select cno,avg(degree) from score group by cno;
+-------+-------------+
| cno | avg(degree) |
+-------+-------------+
| 3-105 | 87.6667 |
| 3-245 | 76.3333 |
| 6-166 | 81.6667 |
+-------+-------------+
3 rows in set (0.01 sec)
mysql> select * from score a where degree < (select avg(degree) from score b where a.cno=b.cno);
+-----+-------+--------+
| sno | cno | degree |
+-----+-------+--------+
| 105 | 3-245 | 75 |
| 105 | 6-166 | 79 |
| 109 | 3-105 | 76 |
| 109 | 3-245 | 68 |
| 109 | 6-166 | 81 |
+-----+-------+--------+
5 rows in set (0.02 sec)
32.查询所有任课教师的tname和depart
意味着课程表中安排了课程
mysql> select * from teacher where tnu in (select tnu from course);
+-----+--------+------+---------------------+--------+--------+
| tnu | tname | tsex | tbirthday | prof | depart |
+-----+--------+------+---------------------+--------+--------+
| 804 | 曹操 | 男 | 1958-12-02 00:00:00 | 教授 | 历史系 |
| 825 | 咪蒙 | 女 | 1998-12-12 00:00:00 | 讲师 | 心理系 |
| 831 | 高圆圆 | 女 | 1998-02-22 00:00:00 | 讲师 | 心理系 |
| 856 | 刘备 | 男 | 1968-12-12 00:00:00 | 副教授 | 工程系 |
+-----+--------+------+---------------------+--------+--------+
4 rows in set (0.00 sec)
33.查询至少有两名男生的班号
mysql> select class from student where ssex="男" group by class having count(*)>1;
+-------+
| class |
+-------+
| 95031 |
| 95033 |
+-------+
2 rows in set (0.01 sec)
34.查询student表中不姓"金"的同学记录
mysql> select * from student where sname not like "金%";
+------+----------+------+---------------------+-------+
| snum | sname | ssex | sbirthday | class |
+------+----------+------+---------------------+-------+
| 101 | 廉颇 | 男 | 1977-09-01 00:00:00 | 95033 |
| 102 | 张飞 | 男 | 1979-09-01 00:00:00 | 95033 |
| 103 | 晁盖 | 男 | 1970-09-01 00:00:00 | 95033 |
| 104 | 赵云 | 男 | 1980-09-01 00:00:00 | 95033 |
| 105 | 貂蝉 | 女 | 1994-09-01 00:00:00 | 95031 |
| 106 | 诸葛亮 | 男 | 1977-09-01 00:00:00 | 95031 |
| 108 | 镇关西 | 男 | 1967-09-01 00:00:00 | 95031 |
| 109 | 吴下阿蒙 | 男 | 1987-09-01 00:00:00 | 95031 |
| 110 | 马云 | 男 | 1974-06-03 00:00:00 | 95038 |
+------+----------+------+---------------------+-------+
9 rows in set (0.00 sec)
35.查询student表中每个学生的姓名和年龄
年龄=当前年龄-出生年份
mysql> select year(now());
+-------------+
| year(now()) |
+-------------+
| 2019 |
+-------------+
1 row in set (0.00 sec)
mysql> select year(sbirthday) from student;
+-----------------+
| year(sbirthday) |
+-----------------+
| 1977 |
| 1979 |
| 1970 |
| 1980 |
| 1994 |
| 1977 |
| 1997 |
| 1967 |
| 1987 |
| 1974 |
+-----------------+
10 rows in set (0.00 sec)
mysql> select sname,year(now())-year(sbirthday) as "年龄" from student;
+----------+------+
| sname | 年龄 |
+----------+------+
| 廉颇 | 42 |
| 张飞 | 40 |
| 晁盖 | 49 |
| 赵云 | 39 |
| 貂蝉 | 25 |
| 诸葛亮 | 42 |
| 金莲 | 22 |
| 镇关西 | 52 |
| 吴下阿蒙 | 32 |
| 马云 | 45 |
+----------+------+
10 rows in set (0.00 sec)
36.查询student表中最大和最小的sbirthday日期值
mysql> select max(sbirthday) as "最大",min(sbirthday) as "最小" from student;
+---------------------+---------------------+
| 最大 | 最小 |
+---------------------+---------------------+
| 1997-09-01 00:00:00 | 1967-09-01 00:00:00 |
+---------------------+---------------------+
1 row in set (0.00 sec)
37.以班号和年龄从大到小的顺序查询student表中的全部记录
mysql> select * from student order by class desc,sbirthday;
+------+----------+------+---------------------+-------+
| snum | sname | ssex | sbirthday | class |
+------+----------+------+---------------------+-------+
| 110 | 马云 | 男 | 1974-06-03 00:00:00 | 95038 |
| 103 | 晁盖 | 男 | 1970-09-01 00:00:00 | 95033 |
| 101 | 廉颇 | 男 | 1977-09-01 00:00:00 | 95033 |
| 102 | 张飞 | 男 | 1979-09-01 00:00:00 | 95033 |
| 104 | 赵云 | 男 | 1980-09-01 00:00:00 | 95033 |
| 108 | 镇关西 | 男 | 1967-09-01 00:00:00 | 95031 |
| 106 | 诸葛亮 | 男 | 1977-09-01 00:00:00 | 95031 |
| 109 | 吴下阿蒙 | 男 | 1987-09-01 00:00:00 | 95031 |
| 105 | 貂蝉 | 女 | 1994-09-01 00:00:00 | 95031 |
| 107 | 金莲 | 女 | 1997-09-01 00:00:00 | 95031 |
+------+----------+------+---------------------+-------+
10 rows in set (0.01 sec)
38.查询男教师及其所上的课程
mysql> select * from course where tnu in (select tnu from teacher where tsex="男");
+-------+----------+-----+
| cnu | cname | tnu |
+-------+----------+-----+
| 3-245 | 孙子兵法 | 804 |
| 6-166 | 运筹学 | 856 |
+-------+----------+-----+
2 rows in set (0.00 sec)
39.查询最高分同学的snum、cnu和degree列
mysql> select * from score where degree=(select max(degree) from score);
+-----+-------+--------+
| sno | cno | degree |
+-----+-------+--------+
| 103 | 3-105 | 92 |
+-----+-------+--------+
1 row in set (0.01 sec)
40.查询和张飞同学同性别的所有同学的sname
mysql> select sname from student where ssex = (select ssex from student where sname="张飞");
+----------+
| sname |
+----------+
| 廉颇 |
| 张飞 |
| 晁盖 |
| 赵云 |
| 诸葛亮 |
| 镇关西 |
| 吴下阿蒙 |
| 马云 |
+----------+
8 rows in set (0.01 sec)
41.查询和张飞同性别并同班的同学sname
mysql> select sname from student where ssex = (select ssex from student where sname="张飞") and class = (select class from student where sname="张飞");
+-------+
| sname |
+-------+
| 廉颇 |
| 张飞 |
| 晁盖 |
| 赵云 |
+-------+
4 rows in set (0.00 sec)
42.查询所有选修心理学教育课程的男同学的成绩表
mysql> select * from score
-> where cno=(select cnu from course where cname="心理学教育")
-> and sno in (select snum from student where ssex="男");
+-----+-------+--------+
| sno | cno | degree |
+-----+-------+--------+
| 101 | 3-105 | 90 |
| 102 | 3-105 | 91 |
| 103 | 3-105 | 92 |
| 104 | 3-105 | 89 |
| 109 | 3-105 | 76 |
+-----+-------+--------+
5 rows in set (0.01 sec)
43.使用如下命令建立一个grade表:
mysql> create table grade(
-> low int(3),
-> upp int(3),
-> grade char(1)
-> );
Query OK, 0 rows affected (0.04 sec)
mysql> insert into grade values(90,100,"A");
Query OK, 1 row affected (0.01 sec)
mysql> insert into grade values(80,89,"B");
Query OK, 1 row affected (0.01 sec)
mysql> insert into grade values(70,79,"C");
Query OK, 1 row affected (0.01 sec)
mysql> insert into grade values(60,69,"D");
Query OK, 1 row affected (0.01 sec)
mysql> insert into grade values(0,59,"E");
Query OK, 1 row affected (0.01 sec)
mysql> select * from grade;
+------+------+-------+
| low | upp | grade |
+------+------+-------+
| 90 | 100 | A |
| 80 | 89 | B |
| 70 | 79 | C |
| 60 | 69 | D |
| 0 | 59 | E |
+------+------+-------+
5 rows in set (0.00 sec)
现查询所有同学的snu,cno和grade列
mysql> select sno,cno,grade from score,grade where degree between low and upp;
+-----+-------+-------+
| sno | cno | grade |
+-----+-------+-------+
| 101 | 3-105 | A |
| 102 | 3-105 | A |
| 103 | 3-105 | A |
| 103 | 3-245 | B |
| 103 | 6-166 | B |
| 104 | 3-105 | B |
| 105 | 3-105 | B |
| 105 | 3-245 | C |
| 105 | 6-166 | C |
| 109 | 3-105 | C |
| 109 | 3-245 | D |
| 109 | 6-166 | B |
+-----+-------+-------+
12 rows in set (0.01 sec)
17.SQL的四种连接查询
内链接
inner join 或者 join
外链接
1.左链接left join 或者left outer join
2.右链接right join 或者right outer join
3.完全外链接 full join 或者 full outer join
举例说明:
先创建一个数据库
mysql> create database testjoin;
Query OK, 1 row affected (0.00 sec)
mysql> use testjoin;
Database changed
再创建两个表
mysql> create table person(
-> id int,
-> name varchar(20),
-> cardId int
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> create table card(
-> id int,
-> name varchar(20)
-> );
Query OK, 0 rows affected (0.03 sec)
mysql> show tables;
+--------------------+
| Tables_in_testjoin |
+--------------------+
| card |
| person |
+--------------------+
2 rows in set (0.00 sec)
添加数据
mysql> insert into card values(1,"饭卡");insert into card values(2,"建行卡");insert into card values(3,"农行卡");insert into card values(4,"工商卡");insert into card values(5,"邮政卡");
Query OK, 1 row affected (0.01 sec)
Query OK, 1 row affected (0.00 sec)
Query OK, 1 row affected (0.00 sec)
Query OK, 1 row affected (0.00 sec)
Query OK, 1 row affected (0.00 sec)
mysql> select * from card;
+------+--------+
| id | name |
+------+--------+
| 1 | 饭卡 |
| 2 | 建行卡 |
| 3 | 农行卡 |
| 4 | 工商卡 |
| 5 | 邮政卡 |
+------+--------+
5 rows in set (0.00 sec)
mysql> insert into person values(1,"张三",1);insert into person values(2,"李四",3);insert into person values(3,"王五",6);
Query OK, 1 row affected (0.01 sec)
Query OK, 1 row affected (0.00 sec)
Query OK, 1 row affected (0.00 sec)
mysql> select * from person;
+------+------+--------+
| id | name | cardId |
+------+------+--------+
| 1 | 张三 | 1 |
| 2 | 李四 | 3 |
| 3 | 王五 | 6 |
+------+------+--------+
3 rows in set (0.00 sec)
并没有创建外键,
1.inner join 查询(内连接)
mysql> select * from person inner join card on person.cardId=card.id;
+------+------+--------+------+--------+
| id | name | cardId | id | name |
+------+------+--------+------+--------+
| 1 | 张三 | 1 | 1 | 饭卡 |
| 2 | 李四 | 3 | 3 | 农行卡 |
+------+------+--------+------+--------+
2 rows in set (0.01 sec)
2.left join(左外链接)
会把左边表里面的所有数据取出来,而右边表中的数据,如果有相等的就显示出来,如果没有就补NULL
mysql> select * from person left join card on person.cardId=card.id;
+------+------+--------+------+--------+
| id | name | cardId | id | name |
+------+------+--------+------+--------+
| 1 | 张三 | 1 | 1 | 饭卡 |
| 2 | 李四 | 3 | 3 | 农行卡 |
| 3 | 王五 | 6 | NULL | NULL |
+------+------+--------+------+--------+
3 rows in set (0.00 sec)
3.right join(右外链接)
会把右边表里面的所有数据取出来,而左边表中的数据,如果有相等的就显示出来,如果没有就补NULL
mysql> select * from person right join card on person.cardId=card.id;
+------+------+--------+------+--------+
| id | name | cardId | id | name |
+------+------+--------+------+--------+
| 1 | 张三 | 1 | 1 | 饭卡 |
| 2 | 李四 | 3 | 3 | 农行卡 |
| NULL | NULL | NULL | 2 | 建行卡 |
| NULL | NULL | NULL | 4 | 工商卡 |
| NULL | NULL | NULL | 5 | 邮政卡 |
+------+------+--------+------+--------+
5 rows in set (0.00 sec)
4.full join(全外链接)
mysql不支持全外链接
mysql> select * from person full join card on person.cardId=card.id;
ERROR 1054 (42S22): Unknown column 'person.cardId' in 'on clause'
如何实现,通过union合并左右连接
mysql> select * from person left join card on person.cardId=card.id
-> union
-> select * from person right join card on person.cardId=card.id;
+------+------+--------+------+--------+
| id | name | cardId | id | name |
+------+------+--------+------+--------+
| 1 | 张三 | 1 | 1 | 饭卡 |
| 2 | 李四 | 3 | 3 | 农行卡 |
| 3 | 王五 | 6 | NULL | NULL |
| NULL | NULL | NULL | 2 | 建行卡 |
| NULL | NULL | NULL | 4 | 工商卡 |
| NULL | NULL | NULL | 5 | 邮政卡 |
+------+------+--------+------+--------+
6 rows in set (0.01 sec)
18.mysql事务
mysql中,事务其实是一个最小的不可分割的工作单元.事务能够保证一个业务的完整性
比如我们的银行转账:
a→-100
update user set money=money-100 where name="a";
b→+100
update user set money=money+100 where name="b";
在实际的程序中,如果只有一条语句执行成功,而另外一条没有执行成功?
出现数据前后不一致.
多条sql语句,可能会有同时成功的要求,要么同时成功或者同时失败
mysql中如何控制事务?
1.mysql默认是开启事务的(自动提交)
mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 1 |
+--------------+
1 row in set (0.00 sec)
默认事务开启的作用是什么?
当我们去执行一个sql语句的时候,效果会立即体现出来,且不能回滚
mysql> create database bank;
Query OK, 1 row affected (0.00 sec)
mysql> use bank;
Database changed
mysql> create table user(
-> id int primary key,
-> name varchar(20),
-> money int
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> insert into user values(1,"a",1000);
Query OK, 1 row affected (0.01 sec)
mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 1000 |
+----+------+-------+
1 row in set (0.00 sec)
事务回滚:撤销sql语句执行效果
rollback;
mysql> rollback;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 1000 |
+----+------+-------+
1 row in set (0.00 sec)
可以看到回滚失败,如何解决呢?
设置mysql自动提交为false
mysql> set autocommit=0;
Query OK, 0 rows affected (0.01 sec)
mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 0 |
+--------------+
1 row in set (0.00 sec)
上面的操作,关闭了mysql的自动提交
mysql> insert into user values(2,"b",1000);
Query OK, 1 row affected (0.00 sec)
mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 1000 |
| 2 | b | 1000 |
+----+------+-------+
2 rows in set (0.00 sec)
mysql> rollback;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 1000 |
+----+------+-------+
1 row in set (0.00 sec)
再一次插入数据
mysql> insert into user values(2,"b",1000);
Query OK, 1 row affected (0.01 sec)
手动提交数据
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
再撤销是不可逆的(持久性)
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 1000 |
| 2 | b | 1000 |
+----+------+-------+
2 rows in set (0.00 sec)
自动提交@@autocommit=1
手动提交commit
事务回滚rollback
如果说这个时候转账
mysql> update user set money=money-100 where name="a";
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update user set money=money+100 where name="b";
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 900 |
| 2 | b | 1100 |
+----+------+-------+
2 rows in set (0.00 sec)
mysql> rollback;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 1000 |
| 2 | b | 1000 |
+----+------+-------+
2 rows in set (0.00 sec)
事务给我们提供了一个返回的机会
mysql> set autocommit=1;
Query OK, 0 rows affected (0.00 sec)
mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 1 |
+--------------+
1 row in set (0.00 sec)
begin;或者start transaction都可以帮我们手动开启一个事物
mysql> update user set money=money-100 where name="a";
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update user set money=money+100 where name="b";
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 900 |
| 2 | b | 1100 |
+----+------+-------+
2 rows in set (0.00 sec)
事务回滚
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
没有被撤销
mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 900 |
| 2 | b | 1100 |
+----+------+-------+
2 rows in set (0.00 sec)
但是在执行sql语句的时候在前面加上begin就可以被撤销
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update user set money=money-100 where name="a";
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update user set money=money+100 where name="b";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 800 |
| 2 | b | 1200 |
+----+------+-------+
2 rows in set (0.00 sec)
mysql> rollback;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 900 |
| 2 | b | 1100 |
+----+------+-------+
2 rows in set (0.00 sec)
看看加上start transaction;同样可以回滚
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> update user set money=money-100 where name="a";
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update user set money=money+100 where name="b";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 800 |
| 2 | b | 1200 |
+----+------+-------+
2 rows in set (0.00 sec)
mysql> rollback;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 900 |
| 2 | b | 1100 |
+----+------+-------+
2 rows in set (0.00 sec)
事务开启之后,一旦commit提交,就不可以回滚(也就是当前的这个事务在提交的时候就结束了)
mysql> update user set money=money-100 where name="a";
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update user set money=money+100 where name="b";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 800 |
| 2 | b | 1200 |
+----+------+-------+
2 rows in set (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 800 |
| 2 | b | 1200 |
+----+------+-------+
2 rows in set (0.00 sec)
事务的四大特征:
A 原子性:事务是最小的单位,不可以再分割
C 一致性:事务要求,同一事物的sql语句,必须保证同时成功或者同时失败
I 隔离性:事务1和事务2是具有隔离性的
D 持久性:事务一旦结束(commit,rollback),就不可以返回
事务开启:
1.修改默认提交 set autocommit=0;
2.begin;
3.start transaction
事务手动提交:commit
事务手动回滚:rollback
事务的隔离性:
1.read uncommited; 读未提交的
2.read commited; 读已经提交的
3.repeatable read; 可以重复读
4.serializable; 串行化
1-read uncommited
如果有事务a和事务b,
a 事务对数据进行操作,在操作的过程中,事务没有被提交,但是b可以看见a操作的结果
bank数据库 user表
mysql> insert into user values(3,"小明",1000);
Query OK, 1 row affected (0.01 sec)
mysql> insert into user values(4,"淘宝店",1000);
Query OK, 1 row affected (0.01 sec)
mysql> select * from user;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | a | 800 |
| 2 | b | 1200 |
| 3 | 小明 | 1000 |
| 4 | 淘宝店 | 1000 |
+----+--------+-------+
4 rows in set (0.00 sec)
如何查看数据库的隔离级别?
mysql 8.0:
系统级别
select @@global.transaction_isolation;
会话级别
select @@transaction_isolation;
mysql 5.x:
mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ |
+-----------------------+
1 row in set (0.01 sec)
或者
select @@tx_isolation;
如何修改隔离级别?
mysql> set global transaction isolation level Read unCommitted;
Query OK, 0 rows affected (0.00 sec)
mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| READ-UNCOMMITTED |
+-----------------------+
1 row in set (0.00 sec)
转账:小明在淘宝店买鞋子:100元
小明→成都 ATM
淘宝店→广州 ATM
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> update user set money=money-100 where name="小明";
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update user set money=money+100 where name="淘宝店";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from user;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | a | 800 |
| 2 | b | 1200 |
| 3 | 小明 | 900 |
| 4 | 淘宝店 | 1100 |
+----+--------+-------+
4 rows in set (0.00 sec)
给淘宝店打电话去查账
淘宝店在广州查账到账了
mysql> use bank;
Database changed
mysql> select * from user;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | a | 800 |
| 2 | b | 1200 |
| 3 | 小明 | 900 |
| 4 | 淘宝店 | 1100 |
+----+--------+-------+
4 rows in set (0.00 sec)
晚上去消费了1100,结账的时候发现钱不够,原因是,小明在成都做了rollback操作
mysql> rollback;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from user;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | a | 800 |
| 2 | b | 1200 |
| 3 | 小明 | 1000 |
| 4 | 淘宝店 | 1000 |
+----+--------+-------+
4 rows in set (0.00 sec)
如果两个不同的地方,都在进行操作,如果事务a开启之后,他的数据可以被其他事务读取到
这样就会出现脏读
脏读:一个事务读到了另外一个事务没有提交的数据.
实际开发是不允许脏读出现的
2.read committed;读取已经提交的
先修改隔离级别为READ-COMMITTED
mysql> set global transaction isolation level read committed;
Query OK, 0 rows affected (0.01 sec)
mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| READ-COMMITTED |
+-----------------------+
1 row in set (0.00 sec)
bank 数据库 user 表
小张:银行的会计
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from user;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | a | 800 |
| 2 | b | 1200 |
| 3 | 小明 | 1000 |
| 4 | 淘宝店 | 1000 |
+----+--------+-------+
4 rows in set (0.01 sec)
小张出去上厕所了,然后:
小王新开了一个户
mysql> use bank;
Database changed
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into user values(5,"c",100);
Query OK, 1 row affected (0.02 sec)
mysql> commit;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from user;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | a | 800 |
| 2 | b | 1200 |
| 3 | 小明 | 1000 |
| 4 | 淘宝店 | 1000 |
| 5 | c | 100 |
+----+--------+-------+
5 rows in set (0.00 sec)
小张上完厕所回来了
mysql> select avg(money) from user;
+------------+
| avg(money) |
+------------+
| 820.0000 |
+------------+
1 row in set (0.00 sec)
money的平均值不是1000,变少了?
虽然只能读到另外一个事物提交的数据,但还是会出现问题,就是,
读取同一个表的数据,发现前后不一致,所以说在
read committed下,会出现不可重复读的现象
3.repeatable read:可重复读
mysql> set global transaction isolation level repeatable read;
Query OK, 0 rows affected (0.00 sec)
mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ |
+-----------------------+
1 row in set (0.01 sec)
在REPEATABLE-READ隔离级别下又会出现什么问题?
mysql> select * from user;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | a | 800 |
| 2 | b | 1200 |
| 3 | 小明 | 1000 |
| 4 | 淘宝店 | 1000 |
| 5 | c | 100 |
+----+--------+-------+
5 rows in set (0.01 sec)
张全蛋–成都
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
王尼玛–北京
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
查询数据
mysql> select * from user;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | a | 800 |
| 2 | b | 1200 |
| 3 | 小明 | 1000 |
| 4 | 淘宝店 | 1000 |
| 5 | c | 100 |
+----+--------+-------+
5 rows in set (0.01 sec)
张全蛋–成都
mysql> insert into user values(6,"d",1000);
Query OK, 1 row affected (0.01 sec)
mysql> commit;
Query OK, 0 rows affected (0.01 sec)
查询数据
mysql> select * from user;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | a | 800 |
| 2 | b | 1200 |
| 3 | 小明 | 1000 |
| 4 | 淘宝店 | 1000 |
| 5 | c | 100 |
| 6 | d | 1000 |
+----+--------+-------+
6 rows in set (0.01 sec)
张全蛋提交之后王尼玛再查询数据
mysql> select * from user;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | a | 800 |
| 2 | b | 1200 |
| 3 | 小明 | 1000 |
| 4 | 淘宝店 | 1000 |
| 5 | c | 100 |
+----+--------+-------+
5 rows in set (0.00 sec)
这时候王尼玛这边再进行插入
结果报错
mysql> insert into user values(6,"d",1000);
ERROR 1062 (23000): Duplicate entry '6' for key 'PRIMARY'
这种现象就叫做幻读:
事务a和事务b同时操作一张表,事务a提交的数据也不能被事务b读到,就会出现幻读.
4.serializable 串行化
修改隔离级别串行化
mysql> set global transaction isolation level serializable;
Query OK, 0 rows affected (0.00 sec)
mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| SERIALIZABLE |
+-----------------------+
1 row in set (0.00 sec)
张全蛋-成都
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
王尼玛-北京
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
张全蛋-成都
mysql> insert into user values(7,"花木兰",1000);
Query OK, 1 row affected (0.01 sec)
mysql> commit;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from user;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | a | 800 |
| 2 | b | 1200 |
| 3 | 小明 | 1000 |
| 4 | 淘宝店 | 1000 |
| 5 | c | 100 |
| 6 | d | 1000 |
| 7 | 花木兰 | 1000 |
+----+--------+-------+
7 rows in set (0.01 sec)
王尼玛-北京
mysql> select * from user;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | a | 800 |
| 2 | b | 1200 |
| 3 | 小明 | 1000 |
| 4 | 淘宝店 | 1000 |
| 5 | c | 100 |
| 6 | d | 1000 |
| 7 | 花木兰 | 1000 |
+----+--------+-------+
7 rows in set (0.00 sec)
张全蛋-成都
进行写入操作是卡住了
mysql> insert into user values(8,"穆桂英",1000);
王尼玛-北京
事务一旦提交,张全蛋的插入数据就可以执行了
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
张全蛋-成都
mysql> insert into user values(8,"穆桂英",1000);
Query OK, 1 row affected (11.62 sec)
当user表被另外一个事务操作的时候,其他事务里面的写操作是不可进行的,
只能进入排队状态(串行化),直到王尼玛那边事务结束之后,张全蛋的这个写入操作才会执行(在没有等待超时的情况下)
那么串行化带来的问题是,性能特差
性能由好到差排序
READ-UNCOMMITTED > READ-COMMITTED>REPEATABLE-READ>SERIALIZABLE
隔离级别越高,性能越差
mysql默认隔离级别是REPEATABLE-READ