Mysql笔记整理

PS:Mysql不区分大小写
一、如何使用终端操作数据库
1.如何登陆数据库服务器

mysql -uroot -p123456

2.如何查询数据库服务器中所有的数据库

show databases;

3.如何选中某一个数据库进行操作

use XXX;(某小数据库名称)
select * from XXX(该数据库里表的名称);      //查询语句
select * from XXX where ID=1;       //选中该表里的ID(字段)=1的记录

4.如何退出数据库服务器

exit;

5.如何在数据库服务器中创建我们的数据库

create database XXX;

6.如何查看某个数据库中的所有数据表

show tables;       //显示该数据库里的表

7.如何创建一个数据表

CREATE TABLE pet(
name VARCHAR(20),
owner VARCHAR(20),
species VARCHAR(20),
sex CHAR(1),
birth DATE,
death DATE);

8.如何查看数据表的具体结构

describe XXX;
desc XXX;  //简写版

(增删查改开始)
9.查看数据表中的记录

select * from XXX(表名);

10.如何向数据表中添加数据记录

INSERT INTO pet VALUES('Puff','Daniel','hamster','f','1999-03-23',NULL);
//最好是要给出明确的列的列表,如:
INSERT INTO pet(name,owner,species,sex,birth,death) VALUES('Puff','Daniel','hamster','f','1999-03-23',NULL);
//ps:可以在insert into中间添加low_priority来降低插入语句的优先级,以此来提高系统处理数据的性能

11.如何删除数据表中的数据记录

delete from pet where name='Puff';

12.如何修改数据库中的数据记录

update pet set name='Cuff' where owner='Daniel';    //相当于通过ID来修改

13.mysql 常用数据类型
大致分为三类:数值、日期/时间、字符串(字符)
具体可见链接
INT FLOAT DOUBLE DATE TIME CHAR VARCHAR TEXT
ps:日期的选择按照格式
数值和字符(串)的选择按照范围大小

14.MySQL建表约束:主键约束、自增约束、外键约束、唯一约束、非空约束、默认约束
主键约束:能够唯一确定一张表中的一条记录,也就是我们通过给某个字段添加约束,就可以使得该字段不重复且不为空

create table user(
ID int primary key,
name varchar(20)
);    //primary key是关键字
insert into user values(1,'Jeff');
insert into user values(1,'Jeff'); //这时会报错,因为ID值已经被主键约束了,它不能重复
insert into user values(NULL,'Jeff'); //这时也会报错,因为ID值已经被主键约束了,它不能为空

联合主键:只要不全一样就行
如何在一张表创建多个主键约束

create table user2(
ID int,
name varchar(20),
password varchar(20),
primary key(ID,name)         //一次性创建多个主键约束
);
insert into user2 values(1,'Joe',123);
insert into user2 values(2,'Joe',123);  //可以
insert into user2 values(1,'Rem',123);  //也可以
insert into user2 values(NULL,'Joe',123);   //不行,主键约束的字段不能为空

自增约束(关键字auto_increment ,常与主键约束结合起来使用)

create table user3(
id int primary key auto_increment,
name varchar(20)
);
insert into user3 (name) values('Oliver');    //指定name字段插入值
insert into user3 (name) values('Biff'); 
select * from user3;
+----+--------+
| id | name   |
+----+--------+
|  1 | Oliver |
|  2 | Biff   |
+----+--------+
2 rows in set (0.00 sec)       //结果id自己自动增加

在创建表时忘记创建主键约束了,如何补上(add)

alter table user4 add primary key(id);

如何删除删除全部字段的主键约束(drop)

alter table user4 drop primary key;  //但是经过补删之后这个字段变得不能为空了,而最开始建表的时候是可以为空的
//疑问?如何删除某一个主键约束呢

如何在已创表上修改某一个字段添加主键约束(modify)

alter table user4 modify id int primary key;

唯一约束:约束修饰的字段的值不能重复(但可以为空)
三种方法添加约束:

alter table user5 add unique(name);
//或者
create table user6(
id int,
name varchar(20) unique
);
//或者
create table user6(
id int,
name varchar(20),
unique(id,name)     //这种情况只要添加的字段值不全一样也可以,类似联合主键
desc user6;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int         | YES  | MUL | NULL    |       |
| name  | varchar(20) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
);
//或者用modify添加
alter table user6 modify name varchar(20) unique;

如何删除唯一约束

alter table user6 drop index id;

非空约束:修饰的字段不能为NULL

create table user7(
id int,
name varchar(20) not null  //(这里用大写小写空都可以)
);

默认约束:当我们插入字段值的时候,如果没有传值,就会使用默认值

create table user8(
id int,
name varchar(20),
age int default 10
);

外键约束:涉及到两个表:父表+子表或者主表+副表

create table classes(
id int primary key,
name varchar(20)
);
create table students(
id int primary key,
name varchar(20),
class_id int,
foreign key(class_id) references classes(id)
);
insert into classes values(1,'一班');
insert into classes values(2,'二班');
insert into classes values(3,'三班');
insert into classes values(4,'四班');
//还可以这样用一条insert语句一次性插入,比多条insert语句性能高,速度快
insert into classes(id,name) values(1,'一班'),(2,'二班'),(3,'三班'),(4,'四班');
insert into students values(1001,'张三',1);
insert into students values(1002,'李四',2);
insert into students values(1001,'王五',2);
insert into students values(1001,'赵六',5);  //报错,因为classes中没有5这个id
//ps:主表中的记录被副表引用之后,是不可以被删除的,如下
delete from classes where id=2;  //报错

15.三大范式
第一范式:1NF
数据表中的所有字段都是不可分割的原子值
如地址字段‘中国四川成都市武侯区武侯大道100号’可以分为‘中国’,‘四川’,‘成都市’,‘武侯区’,‘武侯大道100号’,故它不满足第一范式
PS:范式设计的越详细,对某些操作可能会起到很好的效果,但对某些操作也会产生不好的效果,具体还是要看实际需求。
第二范式:2NF(1NF+除主键外的每一列都必须完全依赖于主键)如果出现不完全依赖的现象,只可能发生在联合主键的情况下

create myorder(
product_id int,
product_name varchar(20),
customer_id int,
customer_name varchar(20),
primary key(product_id,customer_id)
);     //显然product_name依赖于product_id,而与customer_id无关联,customer_name同理,故不满足第二范式,要想满足可以对其拆分,又称拆表,如下所示
create table myorder(
order_id int primary key,
product_id int,
customer_id int
);
create table product(
id int primary key,
name varchar(20)
);
create table customer(
id int primary key,
name varchar(20)
);
//分成三个表后,满足第二范式的设计

第三范式:3NF(2NF+除开主键列的其它列之间不能有传递依赖关系)

create table myorder(
order_id int primary key,
product_id int,
customer_id int,
customer_phone varchar(15)   //既依赖于customer_id,又依赖于myorder_id,故不满足第三范式
);

16.MySQL查询练习
数据准备:
学生表(student):学号、姓名、性别、出生年月日、所在班级
课程表(course):课程号、课程名称、教师编号
教师表(teacher):编号、名字、性别、出生年月日、职称、所在部门
成绩表(score):学生学号、成绩、课程号

create table students(
s_id varchar(10) primary key,
s_name varchar(10) not null,
s_sex varchar(10) not null,
s_birhday datetime,
class varchar(20)
);
create table teachers(
t_id varchar(20) primary key,
t_name varchar(10) not null,
t_sex varchar(10) not null,
t_birthday datetime,
t_pro varchar(10) not null,
t_depart varchar(20) not null
);
create table courses(
c_id varchar(20) primary key,
c_name varchar(20) not null,
t_id varchar(10) not null,
foreign key(t_id) refenrences teachers(t_id)
);
create table scores(
s_id varchar(10) not null,
c_id varchar(20) not null,
points decimal,
foreign key(s_id) references students(s_id),
foreign key(c_id) references courses(c_id),
primary key(s_id,c_id)           //注意!应该设为联合主键,否则一个学生一门课可以出现两个不同的成绩,违背了常理
);
//接下来往学生表里添加数据
insert into students values('101','xz','M','1991-10-02','1班');
insert into students values('103','web','M','1997-04-23','4班');
insert into students values('100','zly','F','1998-05-13','3班');
insert into students values('119','ym','F','2001-01-20','1班');
insert into students values('105','zdy','F','2000-06-21','2班');
insert into students values('123','zyl','M','1996-05-26','4班');
insert into students values('134','zzt','M','1998-10-26','2班');
insert into students values('108','cyq','F','1995-09-21','1班');
select * from students;
+------+--------+-------+---------------------+-------+
| s_id | s_name | s_sex | s_birhday           | class |
+------+--------+-------+---------------------+-------+
| 100  | zly    | F     | 1998-05-13 00:00:00 | 3|
| 101  | xz     | M     | 1991-10-02 00:00:00 | 1|
| 103  | web    | M     | 1997-04-23 00:00:00 | 4|
| 105  | zdy    | F     | 2000-06-21 00:00:00 | 2|
| 108  | cyq    | F     | 1995-09-21 00:00:00 | 1|
| 119  | ym     | F     | 2001-01-20 00:00:00 | 1|
| 123  | zyl    | M     | 1996-05-26 00:00:00 | 4|
| 134  | zzt    | M     | 1998-10-26 00:00:00 | 2|
+------+--------+-------+---------------------+-------+
8 rows in set (0.00 sec)
//接下来往教师表里添加数据
insert into teachers values('803','张三','M','1958-10-09','副教授','计算机系');
insert into teachers values('810','李四','M','1964-11-09','副教授','电子工程系');
insert into teachers values('910','王可','F','1987-09-12','讲师','电子工程系');
insert into teachers values('924','沈川','M','1989-01-01','讲师','计算机系');
select * from teachers;
+------+--------+-------+---------------------+--------+------------+
| t_id | t_name | t_sex | t_birthday          | t_pro  | t_depart   |
+------+--------+-------+---------------------+--------+------------+
| 803  | 张三   | M     | 1958-10-09 00:00:00 | 副教授 | 计算机系   |
| 810  | 李四   | M     | 1964-11-09 00:00:00 | 副教授 | 电子工程系 |
| 910  | 王可   | F     | 1987-09-12 00:00:00 | 讲师   | 电子工程系 |
| 924  | 沈川   | M     | 1989-01-01 00:00:00 | 讲师   | 计算机系   |
+------+--------+-------+---------------------+--------+------------+
4 rows in set (0.00 sec)
//接下来往课程表里添加数据
insert into courses values('001','计算机网络','924');
insert into courses values('002','数据库原理','803');
insert into courses values('004','面向对象程序设计','910');
insert into courses values('003','单片机技术','810');
 select * from courses;
+------+------------------+------+
| c_id | c_name           | t_id |
+------+------------------+------+
| 001  | 计算机网络       | 924  |
| 002  | 数据库原理       | 803  |
| 003  | 单片机技术       | 810  |
| 004  | 面向对象程序设计 | 910  |
+------+------------------+------+
4 rows in set (0.00 sec)
//接下来往成绩表里添加数据
insert into scores values('100','001','98');
insert into scores values('119','002','89');
insert into scores values('134','003','97');
insert into scores values('105','004','86');
insert into scores values('103','003','76');
insert into scores values('101','002','100');
insert into scores values('103','001','99');
insert into scores values('105','001','68');
insert into scores values('134','004','72');
insert into scores values('108','003','66');
select * from scores;
+------+------+--------+
| s_id | c_id | points |
+------+------+--------+
| 100  | 001  |     98 |
| 101  | 002  |    100 |
| 103  | 001  |     99 |
| 103  | 003  |     76 |
| 105  | 001  |     68 |
| 105  | 004  |     86 |
| 108  | 003  |     66 |
| 119  | 002  |     89 |
| 134  | 003  |     97 |
| 134  | 004  |     72 |
+------+------+--------+
10 rows in set (0.00 sec)

开始查询练习:
1.查询students表的所有记录

select * from students;          //*代表的就是这个表里的所有字段
+------+--------+-------+---------------------+-------+
| s_id | s_name | s_sex | s_birhday           | class |
+------+--------+-------+---------------------+-------+
| 100  | zly    | F     | 1998-05-13 00:00:00 | 3|
| 101  | xz     | M     | 1991-10-02 00:00:00 | 1|
| 103  | web    | M     | 1997-04-23 00:00:00 | 4|
| 105  | zdy    | F     | 2000-06-21 00:00:00 | 2|
| 108  | cyq    | F     | 1995-09-21 00:00:00 | 1|
| 119  | ym     | F     | 2001-01-20 00:00:00 | 1|
| 123  | zyl    | M     | 1996-05-26 00:00:00 | 4|
| 134  | zzt    | M     | 1998-10-26 00:00:00 | 2|
+------+--------+-------+---------------------+-------+
8 rows in set (0.00 sec)

2.查询students表中所有记录的s_name,s_sex,class列 //指定某些字段查询

select s_name,s_sex,class from students;
+--------+-------+-------+
| s_name | s_sex | class |
+--------+-------+-------+
| zly    | F     | 3|
| xz     | M     | 1|
| web    | M     | 4|
| zdy    | F     | 2|
| cyq    | F     | 1|
| ym     | F     | 1|
| zyl    | M     | 4|
| zzt    | M     | 2|
+--------+-------+-------+
8 rows in set (0.00 sec)

3.查询教师所有的单位即不重复的depart列

select distinct t_depart from teachers;      //distinct关键字 排除重复
+------------+
| t_depart   |
+------------+
| 计算机系   |
| 电子工程系 |
+------------+
2 rows in set (0.00 sec)

4.查询scores表中成绩在60-80之间的记录(查询区间 between…and…)

 select * from scores where points between 60 and 80;
+------+------+--------+
| s_id | c_id | points |
+------+------+--------+
| 103  | 003  |     76 |
| 105  | 001  |     68 |
| 108  | 003  |     66 |
| 134  | 004  |     72 |
+------+------+--------+
4 rows in set (0.00 sec)
//法二:直接使用运算符来比较
select * from scores where points > 60 and points < 80;
+------+------+--------+
| s_id | c_id | points |
+------+------+--------+
| 103  | 003  |     76 |
| 105  | 001  |     68 |
| 108  | 003  |     66 |
| 134  | 004  |     72 |
+------+------+--------+
4 rows in set (0.00 sec)

5.查询scores表中成绩为89,99或100的记录
法一:(in)

select * from scores where points in(89,99,100);
+------+------+--------+
| s_id | c_id | points |
+------+------+--------+
| 101  | 002  |    100 |
| 103  | 001  |     99 |
| 119  | 002  |     89 |
+------+------+--------+
3 rows in set (0.00 sec)

法二:(or关键字)

select * from scores where points = 89 or points = 99 or points = 100;
+------+------+--------+
| s_id | c_id | points |
+------+------+--------+
| 101  | 002  |    100 |
| 103  | 001  |     99 |
| 119  | 002  |     89 |
+------+------+--------+
3 rows in set (0.00 sec)

6.查询students中‘1班’或性别为女的同学的记录(or关键字)

select * from students where class='1班' or s_sex='F';
+------+--------+-------+---------------------+-------+
| s_id | s_name | s_sex | s_birhday           | class |
+------+--------+-------+---------------------+-------+
| 100  | zly    | F     | 1998-05-13 00:00:00 | 3|
| 101  | xz     | M     | 1991-10-02 00:00:00 | 1|
| 105  | zdy    | F     | 2000-06-21 00:00:00 | 2|
| 108  | cyq    | F     | 1995-09-21 00:00:00 | 1|
| 119  | ym     | F     | 2001-01-20 00:00:00 | 1|
+------+--------+-------+---------------------+-------+
5 rows in set (0.00 sec)

7.以class降序查询student表中的所有记录(升序asc关键字,降序desc关键字) 来自于ascend上升,descend下降

select * from students order by class desc;
+------+--------+-------+---------------------+-------+
| s_id | s_name | s_sex | s_birhday           | class |
+------+--------+-------+---------------------+-------+
| 103  | web    | M     | 1997-04-23 00:00:00 | 4|
| 123  | zyl    | M     | 1996-05-26 00:00:00 | 4|
| 100  | zly    | F     | 1998-05-13 00:00:00 | 3|
| 105  | zdy    | F     | 2000-06-21 00:00:00 | 2|
| 134  | zzt    | M     | 1998-10-26 00:00:00 | 2|
| 101  | xz     | M     | 1991-10-02 00:00:00 | 1|
| 108  | cyq    | F     | 1995-09-21 00:00:00 | 1|
| 119  | ym     | F     | 2001-01-20 00:00:00 | 1|
+------+--------+-------+---------------------+-------+
8 rows in set (0.00 sec)

ps:一般不写的话默认是升序
8.先以c_id升序、再以points降序查询scores表中的所有记录

select * from scores order by c_id asc,points desc;         //谁写在前面就先以谁为标准
+------+------+--------+
| s_id | c_id | points |
+------+------+--------+
| 103  | 001  |     99 |
| 100  | 001  |     98 |
| 105  | 001  |     68 |
| 101  | 002  |    100 |
| 119  | 002  |     89 |
| 134  | 003  |     97 |
| 103  | 003  |     76 |
| 108  | 003  |     66 |
| 105  | 004  |     86 |
| 134  | 004  |     72 |
+------+------+--------+
10 rows in set (0.00 sec)

9.查询‘1班’的人数(count关键字)

select count(*) from students where class='1班';
+----------+
| count(*) |
+----------+
|        3 |
+----------+
1 row in set (0.00 sec)

10.查询score表中的最高分的学生的学号和课程号

select s_id,c_id from scores order by points desc limit 0,1;   //limit第一个数字表示从多少开始(注意我们看到的第一个实际上是第0个),第二个数字表示查多少条记录
+------+------+
| s_id | c_id |
+------+------+
| 101  | 002  |
+------+------+
1 row in set (0.00 sec)

或者

select s_id,c_id from scores where points=(select max(points) from scores);            //子查询,复合语句,嵌套语句
+------+------+
| s_id | c_id |
+------+------+
| 101  | 002  |
+------+------+
1 row in set (0.00 sec)

11.查询每门课的平均成绩(avg方法)

select * from courses;
+------+------------------+------+
| c_id | c_name           | t_id |
+------+------------------+------+
| 001  | 计算机网络       | 924  |
| 002  | 数据库原理       | 803  |
| 003  | 单片机技术       | 810  |
| 004  | 面向对象程序设计 | 910  |
+------+------------------+------+
4 rows in set (0.00 sec)

select avg(points) from scores where c_id='001';
+-------------+
| avg(points) |
+-------------+
|     88.3333 |
+-------------+
1 row in set (0.00 sec)

如何一次性打印出来(用group by 分组)

select c_id,avg(points) from scores group by c_id;

12.查询scores表中至少有两名学生选修的并以0开头的课程的平均分数
(关键字having 分组条件,常见于group by之后)(关键字like 模糊查询)
having和where相似,区别是where筛选分组之前的,having筛选分组之后的

select c_id,avg(points) from scores group by c_id having count(c_id>=2) and c_id like '0%';
+------+-------------+
| c_id | avg(points) |
+------+-------------+
| 001  |     88.3333 |
| 002  |     94.5000 |
| 003  |     79.6667 |
| 004  |     79.0000 |
+------+-------------+
4 rows in set (0.02 sec)

13.查询分数大于70,小于90的s_id列

select s_id,points from scores where points>70 and points<90;
+------+--------+
| s_id | points |
+------+--------+
| 103  |     76 |
| 105  |     86 |
| 119  |     89 |
| 134  |     72 |
+------+--------+
4 rows in set (0.00 sec)

14.查询所有学生的s_name,c_id,points列(多表查询)
步骤:先一个一个表查,再找出每个表中的共同字段,利用这个字段建立起关系

select s_name,c_id,points from students,scores where students.s_id=scores.s_id;         //利用一个桥梁将两张表合成一张
+--------+------+--------+
| s_name | c_id | points |
+--------+------+--------+
| zly    | 001  |     98 |
| xz     | 002  |    100 |
| web    | 001  |     99 |
| web    | 003  |     76 |
| zdy    | 001  |     68 |
| zdy    | 004  |     86 |
| cyq    | 003  |     66 |
| ym     | 002  |     89 |
| zzt    | 003  |     97 |
| zzt    | 004  |     72 |
+--------+------+--------+
10 rows in set (0.01 sec)

再如查询所有学生的s_id,c_name,points列

select s_id,c_name,points from courses,scores where courses.c_id=scores.c_id;
+------+------------------+--------+
| s_id | c_name           | points |
+------+------------------+--------+
| 100  | 计算机网络       |     98 |
| 103  | 计算机网络       |     99 |
| 105  | 计算机网络       |     68 |
| 101  | 数据库原理       |    100 |
| 119  | 数据库原理       |     89 |
| 103  | 单片机技术       |     76 |
| 108  | 单片机技术       |     66 |
| 134  | 单片机技术       |     97 |
| 105  | 面向对象程序设计 |     86 |
| 134  | 面向对象程序设计 |     72 |
+------+------------------+--------+
10 rows in set (0.00 sec)

再如查询所有学生的s_name,c_name,points列(三表关联查询)

select s_name,c_name,points from students,courses,scores where students.s_id=scores.s_id and courses.c_id=scores.c_id;    //通过各表中相同的字段来进行连接
+--------+------------------+--------+
| s_name | c_name           | points |
+--------+------------------+--------+
| zly    | 计算机网络       |     98 |
| web    | 计算机网络       |     99 |
| zdy    | 计算机网络       |     68 |
| xz     | 数据库原理       |    100 |
| ym     | 数据库原理       |     89 |
| web    | 单片机技术       |     76 |
| cyq    | 单片机技术       |     66 |
| zzt    | 单片机技术       |     97 |
| zdy    | 面向对象程序设计 |     86 |
| zzt    | 面向对象程序设计 |     72 |
+--------+------------------+--------+
10 rows in set (0.00 sec)
select s_name,c_name,points,students.s_id as snu,   //临时给字段取别名
courses.c_id as cnu from //注意要指明是谁的s_id,是谁的c_id
students,courses,scores 
where students.s_id=scores.s_id 
and courses.c_id=scores.c_id; 
+--------+------------------+--------+-----+-----+
| s_name | c_name           | points | snu | cnu |
+--------+------------------+--------+-----+-----+
| zly    | 计算机网络       |     98 | 100 | 001 |
| xz     | 数据库原理       |    100 | 101 | 002 |
| web    | 计算机网络       |     99 | 103 | 001 |
| web    | 单片机技术       |     76 | 103 | 003 |
| zdy    | 计算机网络       |     68 | 105 | 001 |
| zdy    | 面向对象程序设计 |     86 | 105 | 004 |
| cyq    | 单片机技术       |     66 | 108 | 003 |
| ym     | 数据库原理       |     89 | 119 | 002 |
| zzt    | 单片机技术       |     97 | 134 | 003 |
| zzt    | 面向对象程序设计 |     72 | 134 | 004 |
+--------+----------------

15.查询“1班”学生每门课的平均分(子查询加分组求平均分)

//分3步走,像是写英语长句?哈哈哈
select * from students where class='1班';
+------+--------+-------+---------------------+-------+
| s_id | s_name | s_sex | s_birhday           | class |
+------+--------+-------+---------------------+-------+
| 101  | xz     | M     | 1991-10-02 00:00:00 | 1|
| 108  | cyq    | F     | 1995-09-21 00:00:00 | 1|
| 119  | ym     | F     | 2001-01-20 00:00:00 | 1|
+------+--------+-------+---------------------+-------+
3 rows in set (0.00 sec)
select * from scores where s_id in(select s_id from students where class='1班');
+------+------+--------+
| s_id | c_id | points |
+------+------+--------+
| 101  | 002  |    100 |
| 108  | 003  |     66 |
| 119  | 002  |     89 |
+------+------+--------+
3 rows in set (0.01 sec)
 select c_id,avg(points) from scores where s_id in(select s_id from students where class='1班') group by c_id;
+------+-------------+
| c_id | avg(points) |
+------+-------------+
| 002  |     94.5000 |
| 003  |     66.0000 |
+------+-------------+
2 rows in set (0.00 sec)

16.查询选修“003”课程的成绩高于‘108’号同学“003”成绩的所有同学的记录

select * from scores where points>(select points from scores where s_id=108 and c_id=003) and c_id=003;
+------+------+--------+
| s_id | c_id | points |
+------+------+--------+
| 103  | 003  |     76 |
| 134  | 003  |     97 |
+------+------+--------+
2 rows in set (0.00 sec)

查询成绩高于学号为‘108’,课程号为‘003’的成绩的所有记录

select * from scores where points>(select points from scores where s_id=108 and c_id=003);
+------+------+--------+
| s_id | c_id | points |
+------+------+--------+
| 100  | 001  |     98 |
| 101  | 002  |    100 |
| 103  | 001  |     99 |
| 103  | 003  |     76 |
| 105  | 001  |     68 |
| 105  | 004  |     86 |
| 119  | 002  |     89 |
| 134  | 003  |     97 |
| 134  | 004  |     72 |
+------+------+--------+
9 rows in set (0.00 sec)

17.查询和学号为108,100的同学同年出生的所有学生的s_id,s_name,s_birthday列 (year函数截取年份)

select year(s_birthday) from students where s_id in(100,108);
+-----------------+
| year(s_birhday) |
+-----------------+
|            1998 |
|            1995 |
+-----------------+
2 rows in set (0.00 sec)

select * from students where year(s_birhday) 
in(select year(s_birhday) from students where s_id in(100,108));
+------+--------+-------+---------------------+-------+
| s_id | s_name | s_sex | s_birhday           | class |
+------+--------+-------+---------------------+-------+
| 100  | zly    | F     | 1998-05-13 00:00:00 | 3|
| 108  | cyq    | F     | 1995-09-21 00:00:00 | 1|
| 134  | zzt    | M     | 1998-10-26 00:00:00 | 2|
+------+--------+-------+---------------------+-------+
3 rows in set (0.00 sec)

18.查询沈川教师任课的学生成绩(多层嵌套子查询)

select * from scores where c_id=(select c_id from courses where t_id=(select t_id from teachers where t_name='沈 川'));
+------+------+--------+
| s_id | c_id | points |
+------+------+--------+
| 100  | 001  |     98 |
| 103  | 001  |     99 |
| 105  | 001  |     68 |
+------+------+--------+
3 rows in set (0.00 sec)

查询出计算机系教师所教课程的成绩表

select * from scores where c_id in(select c_id from courses where t_id in(select t_id from teachers where t_depart='计算机系'));
+------+------+--------+
| s_id | c_id | points |
+------+------+--------+
| 101  | 002  |    100 |
| 119  | 002  |     89 |
| 100  | 001  |     98 |
| 103  | 001  |     99 |
| 105  | 001  |     68 |
+------+------+--------+
5 rows in set (0.00 sec)

19.查询选修某课程的同学人数多于2人的教师姓名(分组后条件查询+嵌套查询)

select c_id from scores group by c_id having count(*)>2;
+------+
| c_id |
+------+
| 001  |
| 003  |
+------+
2 rows in set (0.00 sec)
select t_name from teachers 
where t_id in(select t_id from courses where c_id 
in(select c_id from scores group by c_id having count(*)>2));
+--------+
| t_name |
+--------+
| 李四   |
| 沈川   |
+--------+
2 rows in set (0.00 sec)

20.查询教师表中不同职称的教师的t_name和t_pro


21.查询选修编号为‘001’课程且成绩至少高于选修编号为‘002’课程的成绩的同学的c_id,s_id,points,并按points从高到低排序 (any关键字)

select * from scores where c_id=001 
and points>any(select points from scores where c_id=002) 
order by points desc;
+------+------+--------+
| s_id | c_id | points |
+------+------+--------+
| 103  | 001  |     99 |
| 100  | 001  |     98 |
+------+------+--------+
2 rows in set (0.00 sec)

查询选修编号为‘002’且成绩高于选修编号为‘001’课程的同学的c_id,s_id,points列(all关键字)

select * from scores where c_id=002 
and points>all(select points from scores where c_id=001);
+------+------+--------+
| s_id | c_id | points |
+------+------+--------+
| 101  | 002  |    100 |
+------+------+--------+
1 row in set (0.00 sec)

22.查询所有教师和同学的name,sex,birthday(as改别名,union求并集)
ps:这里as可用空格替代,也就是说select s_name name,s_sex sex,s_birthday birthday from students union select t_name,t_sex,t_birthday from teachers;也是可以的

select s_name as name,s_sex as sex,s_birthday as birthday from students
union 
select t_name,t_sex,t_birthday from teachers;
+------+-----+---------------------+
| name | sex | birthday            |
+------+-----+---------------------+
| zly  | F   | 1998-05-13 00:00:00 |
| xz   | M   | 1991-10-02 00:00:00 |
| web  | M   | 1997-04-23 00:00:00 |
| zdy  | F   | 2000-06-21 00:00:00 |
| cyq  | F   | 1995-09-21 00:00:00 |
| ym   | F   | 2001-01-20 00:00:00 |
| zyl  | M   | 1996-05-26 00:00:00 |
| zzt  | M   | 1998-10-26 00:00:00 |
| 张三 | M   | 1958-10-09 00:00:00 |
| 李四 | M   | 1964-11-09 00:00:00 |
| 王可 | F   | 1987-09-12 00:00:00 |
| 沈川 | M   | 1989-01-01 00:00:00 |
+------+-----+---------------------+
12 rows in set (0.00 sec)
//ps:若有重复记录,用union关键字会默认去除重复的多条记录,只保留一条,若用union all关键字就不会去除重复的记录,而是有多少显现多少

23.如何改变表中的某一字段名

alter table students change s_birhday s_birthday datetime;

24.查询成绩比该课程平均成绩低的同学的成绩表

select c_id,avg(points) from scores group by c_id;
+------+-------------+
| c_id | avg(points) |
+------+-------------+
| 001  |     88.3333 |
| 002  |     94.5000 |
| 003  |     79.6667 |
| 004  |     79.0000 |
+------+-------------+
4 rows in set (0.00 sec)

select * from scores a where points<(select avg(points) from scores b where a.c_id=b.c_id);
+------+------+--------+
| s_id | c_id | points |
+------+------+--------+
| 103  | 003  |     76 |
| 105  | 001  |     68 |
| 108  | 003  |     66 |
| 119  | 002  |     89 |
| 134  | 004  |     72 |
+------+------+--------+
5 rows in set (0.00 sec)

25.查询至少有2名男生的班号

select class from students where s_sex='M' group by class having count(*)>1;
+-------+
| class |
+-------+
| 4|
+-------+
1 row in set (0.00 sec)

26.查询students表中不姓z的同学记录(not like关键字 模糊查询取反)

select * from students where s_name not like 'z%';
+------+--------+-------+---------------------+-------+
| s_id | s_name | s_sex | s_birthday          | class |
+------+--------+-------+---------------------+-------+
| 101  | xz     | M     | 1991-10-02 00:00:00 | 1|
| 103  | web    | M     | 1997-04-23 00:00:00 | 4|
| 108  | cyq    | F     | 1995-09-21 00:00:00 | 1|
| 119  | ym     | F     | 2001-01-20 00:00:00 | 1|
+------+--------+-------+---------------------+-------+
4 rows in set (0.00 sec)

27.查询students表中每个学生的姓名和年龄

select year(now());    //当前年份
+-------------+
| year(now()) |
+-------------+
|        2020 |
+-------------+
1 row in set (0.00 sec)

select s_name,year(now())-year(s_birthday) as '年龄' from students;
+--------+------+
| s_name | 年龄 |
+--------+------+
| zly    |   22 |
| xz     |   29 |
| web    |   23 |
| zdy    |   20 |
| cyq    |   25 |
| ym     |   19 |
| zyl    |   24 |
| zzt    |   22 |
+--------+------+
8 rows in set (0.00 sec)

28.查询students表中最大和最小的s_birthday日期值

select max(s_birthday) as '最大日期',min(s_birthday) as '最小日期' from students;
+---------------------+---------------------+
| 最大日期            | 最小日期            |
+---------------------+---------------------+
| 2001-01-20 00:00:00 | 1991-10-02 00:00:00 |
+---------------------+---------------------+
1 row in set (0.00 sec)

29.以班号和年龄从大到小查询students表中的全部记录

select * from students order by class desc,s_birthday;
+------+--------+-------+---------------------+-------+
| s_id | s_name | s_sex | s_birthday          | class |
+------+--------+-------+---------------------+-------+
| 123  | zyl    | M     | 1996-05-26 00:00:00 | 4|
| 103  | web    | M     | 1997-04-23 00:00:00 | 4|
| 100  | zly    | F     | 1998-05-13 00:00:00 | 3|
| 134  | zzt    | M     | 1998-10-26 00:00:00 | 2|
| 105  | zdy    | F     | 2000-06-21 00:00:00 | 2|
| 101  | xz     | M     | 1991-10-02 00:00:00 | 1|
| 108  | cyq    | F     | 1995-09-21 00:00:00 | 1|
| 119  | ym     | F     | 2001-01-20 00:00:00 | 1|
+------+--------+-------+---------------------+-------+
8 rows in set (0.00 sec)

30.按等级查询
假设使用以下命令建立了一个grade表,现查询所有同学的s_id,c_id,grade列

create table grade(low int(3),up int(3),grade char(1));
insert into grade values(90,100,'A');
insert into grade values(80,89,'B');
insert into grade values(70,79,'C');
insert into grade values(60,69,'D');
insert into grade values(0,59,'E');

select s_id,c_id,grade from scores,grade where points between low and up;
+------+------+-------+
| s_id | c_id | grade |
+------+------+-------+
| 100  | 001  | A     |
| 101  | 002  | A     |
| 103  | 001  | A     |
| 103  | 003  | C     |
| 105  | 001  | D     |
| 105  | 004  | B     |
| 108  | 003  | D     |
| 119  | 002  | B     |
| 134  | 003  | A     |
| 134  | 004  | C     |
+------+------+-------+
10 rows in set (0.01 sec)

31.SQL的四种连接查询
内连接inner join 或者join
外连接:
左连接left join或者left outer join
右连接right join或者right outer join
完全外连接full join 或者full outer join

现创建两个表:person表:id,name,cardID
card表:id,name

create table card(id int,name varchar(20));
create table person(id int,name varchar(20),cardID int);

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,'工商卡');
select * from card;
+------+--------+
| id   | name   |
+------+--------+
|    1 | 饭卡   |
|    2 | 邮政卡 |
|    3 | 建行卡 |
|    4 | 农行卡 |
|    5 | 工商卡 |
+------+--------+

insert into person values(1,'沈泽',1);
insert into person values(2,'费悬',1);
insert into person values(3,'骆洲',2);
insert into person values(4,'魏通',5);
insert into person values(5,'蓝章',6);
select * from person;
+------+------+--------+
| id   | name | cardID |
+------+------+--------+
|    1 | 沈泽 |      1 |
|    2 | 费悬 |      1 |
|    3 | 骆洲 |      2 |
|    4 | 魏通 |      5 |
|    5 | 蓝章 |      6 |
+------+------+--------+

可以看到因为没有创建外键约束,因而即使卡号是6也可以插入到person表中

inner join 查询(内联查询,其实就是两张表中的数据通过某个字段相等,查询出相关记录数据)

select * from person inner join card on person.cardID=card.id; 
+------+------+--------+------+--------+
| id   | name | cardID | id   | name   |
+------+------+--------+------+--------+
|    1 | 沈泽 |      1 |    1 | 饭卡   |
|    2 | 费悬 |      1 |    1 | 饭卡   |
|    3 | 骆洲 |      2 |    2 | 邮政卡 |
|    4 | 魏通 |      5 |    5 | 工商卡 |
+------+------+--------+------+--------+
4 rows in set (0.00 sec)
//找到了cardID=card.id的记录,把6号id扔了

left join(左外连接,会把左边表里面的所有数据取出来,而右边表中的数据如果有相等的就显示出来,如果没有就会补上NULL)

select * from person left join card on person.cardID=card.id;
+------+------+--------+------+--------+
| id   | name | cardID | id   | name   |
+------+------+--------+------+--------+
|    1 | 沈泽 |      1 |    1 | 饭卡   |
|    2 | 费悬 |      1 |    1 | 饭卡   |
|    3 | 骆洲 |      2 |    2 | 邮政卡 |
|    4 | 魏通 |      5 |    5 | 工商卡 |
|    5 | 蓝章 |      6 | NULL | NULL   |
+------+------+--------+------+--------+
5 rows in set (0.00 sec)

right join(右外连接,会把右边表里面的所有数据取出来,而左边表中的数据如果有相等的就显示出来,如果没有就会补上NULL)

select * from person right join card on person.cardID=card.id;
+------+------+--------+------+--------+
| id   | name | cardID | id   | name   |
+------+------+--------+------+--------+
|    1 | 沈泽 |      1 |    1 | 饭卡   |
|    2 | 费悬 |      1 |    1 | 饭卡   |
|    3 | 骆洲 |      2 |    2 | 邮政卡 |
| NULL | NULL |   NULL |    3 | 建行卡 |
| NULL | NULL |   NULL |    4 | 农行卡 |
|    4 | 魏通 |      5 |    5 | 工商卡 |
+------+------+--------+------+--------+
6 rows in set (0.00 sec)

full join(全外连接)

select * from person full join card on person.cardID=card.id;
ERROR 1054 (42S22): Unknown column 'person.cardID' in 'on clause' //报错,因为mysql有时不支持full join,但其实效果等同于以下语句

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 | 费悬 |      1 |    1 | 饭卡   |
|    3 | 骆洲 |      2 |    2 | 邮政卡 |
|    4 | 魏通 |      5 |    5 | 工商卡 |
|    5 | 蓝章 |      6 | NULL | NULL   |
| NULL | NULL |   NULL |    3 | 建行卡 |
| NULL | NULL |   NULL |    4 | 农行卡 |
+------+------+--------+------+--------+
7 rows in set (0.00 sec)

ps:我们还可以对表取别名,这样可以缩短sql语句,或者允许在单条select语句中多次使用相同的表

select * from scores as sc,students as st where sc.s_id=st.s_id;
+------+------+--------+------+--------+-------+---------------------+-------+
| s_id | c_id | points | s_id | s_name | s_sex | s_birthday          | class |
+------+------+--------+------+--------+-------+---------------------+-------+
| 100  | 001  |     98 | 100  | zly    | F     | 1998-05-13 00:00:00 | 3|
| 101  | 002  |    100 | 101  | xz     | M     | 1991-10-02 00:00:00 | 1|
| 103  | 001  |     99 | 103  | web    | M     | 1997-04-23 00:00:00 | 4|
| 103  | 003  |     76 | 103  | web    | M     | 1997-04-23 00:00:00 | 4|
| 105  | 001  |     68 | 105  | zdy    | F     | 2000-06-21 00:00:00 | 2|
| 105  | 004  |     86 | 105  | zdy    | F     | 2000-06-21 00:00:00 | 2|
| 108  | 003  |     66 | 108  | cyq    | F     | 1995-09-21 00:00:00 | 1|
| 119  | 002  |     89 | 119  | ym     | F     | 2001-01-20 00:00:00 | 1|
| 134  | 003  |     97 | 134  | zzt    | M     | 1998-10-26 00:00:00 | 2|
| 134  | 004  |     72 | 134  | zzt    | M     | 1998-10-26 00:00:00 | 2|
+------+------+--------+------+--------+-------+---------------------+-------+
//避免s_id字段重复可这样自然联结表:
select st.*,sc.c_id,sc.points from scores as sc,students as st where sc.s_id=st.s_id;
+------+--------+-------+---------------------+-------+------+--------+
| s_id | s_name | s_sex | s_birthday          | class | c_id | points |
+------+--------+-------+---------------------+-------+------+--------+
| 100  | zly    | F     | 1998-05-13 00:00:00 | 3| 001  |     98 |
| 101  | xz     | M     | 1991-10-02 00:00:00 | 1| 002  |    100 |
| 103  | web    | M     | 1997-04-23 00:00:00 | 4| 001  |     99 |
| 103  | web    | M     | 1997-04-23 00:00:00 | 4| 003  |     76 |
| 105  | zdy    | F     | 2000-06-21 00:00:00 | 2| 001  |     68 |
| 105  | zdy    | F     | 2000-06-21 00:00:00 | 2| 004  |     86 |
| 108  | cyq    | F     | 1995-09-21 00:00:00 | 1| 003  |     66 |
| 119  | ym     | F     | 2001-01-20 00:00:00 | 1| 002  |     89 |
| 134  | zzt    | M     | 1998-10-26 00:00:00 | 2| 003  |     97 |
| 134  | zzt    | M     | 1998-10-26 00:00:00 | 2| 004  |     72 |
+------+--------+-------+---------------------+-------+------+--------+

32.MySQL中,事务其实是一个最小的不可分割的工作单元。事务能够保证一个业务的完整性。
举例:比如银行转账
a->-100
update user set money=money-100 where name=‘a’;
b->+100
update user set money=money+100 where name=‘b’;
实际的程序中,如果只有一条语句执行成功,那就会出现数据前后不一致的情况,这就破坏了业务的完整性

MySQL中如何控制事务?
MySQL默认是开启事务的(自动提交)

select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            1 |
+--------------+
1 row in set (0.00 sec)

默认事务开启的作用是:当我们去执行一个sql语句的时候,效果会立即体现出来,且不能回滚(rollback:即撤销sql语句执行效果)。

如何回滚?设置mysql自动提交为false

set autocommit=0;

如果此时又想提交该语句?(手动提交)

commit;

此时再看银行转账:

create table user(id int primary key,name varchar(20),money int);
insert user values(1,'a',1000);
insert user values(2,'b',1000);
select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |  1000 |
|  2 | b    |  1000 |
+----+------+-------+
update user set money=money-100 where id=1;
update user set money=money+100 where id=2;
select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |   900 |
|  2 | b    |  1100 |
+----+------+-------+
2 rows in set (0.00 sec)
rollback;       //并没有回滚,因为此时autocommit还是默认为1
select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |   900 |
|  2 | b    |  1100 |
+----+------+-------+
2 rows in set (0.00 sec)
set autocommit=0;
update user set money=money-100 where id=1;
update user set money=money+100 where id=2;
select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |   800 |
|  2 | b    |  1200 |
+----+------+-------+
2 rows in set (0.00 sec)
rollback;   //回滚奏效了,事务给我们提供了一个返回的机会
select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |   900 |
|  2 | b    |  1100 |
+----+------+-------+
2 rows in set (0.00 sec)
commit;   //此时再提交rollback对该语句就不会奏效了

begin;或者start transaction;都可以帮我们手动开启一个事务(但一旦commit;之后就结束事务了,也就不能回滚了)

begin;
update user set money=money-100 where id=1;
update user set money=money+100 where id=2;
select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |   900 |
|  2 | b    |  1100 |
+----+------+-------+
2 rows in set (0.00 sec)
rollback;                  //回滚奏效了
select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |  1000 |
|  2 | b    |  1000 |
+----+------+-------+
2 rows in set (0.01 sec)

33.事务的四大特征(ACID)
A:原子性:事务是最小的单位,不可以再分割
C:一致性:同一事务中的sql语句,必须保证同时成功或者同时失败(类似银行转账那样)。
I:隔离性:事务1和事务2之间是具有隔离性的
D:持久性:事务一旦结束,就不可返回

34.事务的隔离性:
read uncommitted; 读未提交的
如果有事务a,b,其中a事务对数据进行操作,在操作的过程中事务没有被提交,但是b可以看见a操作的结果,就可能会出现脏读
如何查看数据库的隔离级别?

select @@transaction_isolation;//会话级别的
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ         |    //此为mysql默认的隔离级别
+-------------------------+
1 row in set (0.00 sec)

select @@global.transaction_isolation;   //系统级别的
+--------------------------------+
| @@global.transaction_isolation |
+--------------------------------+
| REPEATABLE-READ                |
+--------------------------------+
1 row in set (0.00 sec)

如何修改隔离级别?

set global transaction isolation level read uncommitted;
select @@global.transaction_isolation;
+--------------------------------+
| @@global.transaction_isolation |
+--------------------------------+
| READ-UNCOMMITTED               |
+--------------------------------+
1 row in set (0.00 sec)

脏读:一个事务读到了另外一个事务没有提交的数据。实际开发中是不允许的

read committed; 读已经提交的
读取同一个表的数据发现前后不一致 出现不可重复度现象(不能同时被两个人或多人共同读取)

repeatable read; 可以重复读
幻读:事务a和事务b同时操作一张表,事务a提交的数据不能被事务b读到,就可能造成幻读

serializable; 串行化
当user表被一个事务操作的时候,其它事务里面的写操作是不可以进行的,会被卡住进入排队状态(串行化),直到那个事务结束(commit;)之后,这边的写入操作才可以继续
串行化问题:性能特别差
性能比较:read uncommitted>read committed>repeatable read>serializable
也就是说隔离级别越高,性能越差

二、
如何使用可视化工具操作数据库

你可能感兴趣的:(Mysql笔记整理)