学习MySQL

有幸在本科期间学过SQL Server这门课程,但是由于年代实在过于久远,加之曾经为了装软件把家里的老电脑装崩了,从此之后数据库就给我留下了阴影,现在已经忘得差不多了。。。而MYSQL拥有安装轻便、使用简单的优点,还是先来学习一下这个吧!

笔记按照b站上的“一天学会MySQL”课程为顺序,一天学完。。。是不太可能的了

目录

一、基础语法

1.登录数据库

在命令提示符—管理员中打开(CMD/Ctrl+R)

Users>mysql -uroot 用户名 

Welcome to the MySQL monitor.  Commands end with ; or \g.Your MySQL connection id is 4
Server version: 5.7.20 MySQL Community Server (GPL) Copyright (c) 2000, 2017, 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.

2.随时退出数据库

mysql>exit
bye

mysql>\q
bye

或者ctrl+z

mysql>^z
bye

语句中注意一定要写“;”

3.在数据库服务其中创建一个新的数据库(test)

mysql>create database test;
Query OK, 1 row affected (0.01 sec)

查看MYSQL已创建的所有的数据库:

show databases;

学习MySQL

4.删除该某数据库(ppt):

drop database ppt;

学习MySQL

5.使用数据库服务器中的某一数据库(test)

mysql>use test;
Database changed

6.查看某数据库(test)中的所有数据表

mysql>show tables;
Empty set (0.00 sec)                     \*代表数据表为空

7.在某数据库下创建一个新数据表(pet)**

注意;一定要加入“,”,MYSQL对大小写不敏感

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.05 sec)

再次查看是否创建成功:

mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| pet            |
+----------------+
1 row in set (0.00 sec)

mysql常用数据类型
支持多种类型,大致可以分为三类:数值、日期/时间、字符串(字符)类型。

为了不破坏教程的完整性,详情可见mysql的常用数据类型

7.删除数据表(以表user4为例):

mysql> drop table user4;
Query OK, 0 rows affected (0.01 sec)

8.查看创建好的数数据表(table名为pet)的结构

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.02 sec)

Field 字段
Type 字段类型
Null 是否允许为空
Key 表示约束相关
Default 默认值为空

9.查看数据表(pet)内的记录**

mysql> select * from pet;
Empty set (0.00 sec)

9.为已有数据表(student)增加属性(增加列)
eg. sbirthday为属性名,datetime为属性类型


 ALTER TABLE **student** ADD COLUMN **sbirthday** **datetime**;

10.向数据表(pet)中添加数据记录**

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  |
+----------+-------+---------+------+------------+-------+
1 row in set (0.00 sec)

多次添加数据,需要多次重复上述两条指令
再次查看:
学习MySQL

11.删除数据表(pet)中的数据**

mysql> delete from pet where name='ufl';
Query OK, 1 row affected (0.02 sec)

删除后:
学习MySQL
(后续删除了最后重复的一条数据)

12.修改数据表(pet)中的数据**

mysql> update set name='所有者' where owner='Harold';
Query OK, 1 row affected (0.01 sec)                             

学习MySQL

13.修改数据表名称(从user7→user6)**

 mysql>alter table user7 rename to user6;
Query OK, 0 rows affected (0.02 sec)

学习MySQL

小总结:

  • 增加 insert
  • 删除 delete
  • 修改 unpdate
  • 查询 select

二、约束

1.主键约束 (primary key)

能够唯一确定一张表中的一条记录,也就是我们通过对某个字段添加约束,就可以使该字段不重复且不为空。

(1)在某一属性上试用 primary key
在这里,我们创建一个新的数据表 user 供使用

mysql> create table user(
    -> id int primary key,
    -> name varchar(20));
Query OK, 0 rows affected (0.02 sec)

学习MySQL
学习MySQL

mysql> insert into user values('1','zhangsan');
Query OK, 1 row affected (0.01 sec)

再次输入:不可

mysql>  insert into user values('1','zhangsan');
ERROR 1062 (23000):                                              \*Duplicateentry '1' fro key 'PRIMARY'  ————因为之前在id部分的设置,不可提交重复的内容

id输入null:不可

mysql>  insert into user values(null,'zhangsan');
ERROR 1048 (23000): Unknown error 1048                           \*  Column 'id' cannot be null                

更改id:可

mysql>  insert into user values('2','zhangsan');
Query OK, 1 row affected (0.01 sec)                                           

学习MySQL

(2)限定于多种属性上:联合主键
——只要联合的主键值中某一个不重复即可通过(类似于非门+);但联合主键的任一字段不可为空

eg.先创建一个新的表 user2;

mysql> create table user2(
    -> id int,
    -> name varchar(20),
    -> password varchar(20),
    -> primary key(id,name));                      \*联合主键
Query OK, 0 rows affected (0.03 sec)

插入一条信息:

mysql> insert into user2 values(1,'zhangsan','123');
Query OK, 1 row affected (0.01 sec)

重复插入同样的信息,报错

 insert into user2 values(1,'zhangsan','123');
 ERROR 1062 (23000):

改变某一(id)信息,重复插入,成功(说明只要一个成立即可)

mysql>  insert into user2 values(2,'zhangsan','123');
Query OK, 1 row affected (0.01 sec)

设置id为null:

mysql> insert into user2 values(null,'wanger','123');
ERROR 1048 (23000): Unknown error 1048                                       \*ERROR 1048 (23000):Column 'id' cannot be null 任一字段不可为空

2.自增约束

与 1.主键约束primary key 配合使用,会自动管控相应的值,使其自动增长

eg.
创建新的表user3

mysql> create table user3(
    -> id int primary key auto_increment,
    -> name varchar(20));
Query OK, 0 rows affected (0.02 sec)

在指定字段 name上加入信息:

mysql> insert into user3 (name) values('zhangsan');
Query OK, 1 row affected (0.01 sec)

此时自动生成了id
学习MySQL
再次插入一个name:

mysql> insert into user3 (name) values('zhangsan');
Query OK, 1 row affected (0.01 sec)

此时自动产生id=2
学习MySQL
——倘若没有在创立表格时添加约束,接下来该如何处理?

eg.创建新表user4,含id,name

mysql>  create table user4(
    -> id int,
    -> name varchar(20)
    -> );

在表(user4)中修改表结构,添加对某一属性(id)的主键约束:

mysql> alter table user4 add primary key(id);
 Query OK, 0 rows affected (0.04 sec)

如果需要对多个属性添加约束:

mysql>  alter table user4 add primary key(id,name);
Query OK, 0 rows affected (0.04 sec)

Modify:或者以修改表(user4)中的属性(以修改id属性为例)添加约束

mysql> alter table user4 modify id int primary key;
Query OK, 0 rows affected (0.03 sec)

查看修改后的情况:(desc是describe命令的缩写)

mysql> desc user4;

学习MySQL
删除主键约束:

mysql> alter table user4 drop primary key;
Query OK, 0 rows affected (0.04 sec)

所有主键约束均被删除:
学习MySQL

3.唯一约束

约束修饰的字段的值不能重复

eg.创建一个仅id和name属性的数据表(user5)

Unique添加唯一约束:

mysql> alter table user5 add unique(name);
Query OK, 0 rows affected (0.02 sec)

或MODIFY添加:

mysql> alter table user5 modify name varchar(20) unique;

直接添加:

mysql>  create table user7(
    -> id int,
    -> name varchar(20) unique
    -> );

mysql>  create table user7(
    -> id int,
    -> name varchar(20) ,
       -> unique(name)
    -> );

学习MySQL

效果:插入数据后,再次插入已设置属性(name)下相同数据时报错

mysql> insert into user5 values(1,'zhagnsan');
Query OK, 1 row affected (0.01 sec)

mysql> insert into user5 values(2,'zhagnsan');
ERROR 1062 (23000):

若同时在为多种属性(id,name)添加唯一约束

mysql> create table user8(
    -> id int,
    -> name varchar(20),
    -> unique(id,name)                          \*两种中有一种属性满足唯一约束条件即可通过,类似于“或”
    -> );

key标识变为MUL
学习MySQL
eg.插入数据

mysql> insert into user8 values(1,'zhangsan');
Query OK, 1 row affected (0.01 sec)

mysql>  insert into user8 values(1,'zhangsan');                           \*重新输入相同的id和name
ERROR 1062 (23000):

mysql> insert into user8 values(2,'zhangsan');                            \*改变id
Query OK, 1 row affected (0.01 sec)

mysql>  insert into user8 values(1,'zhangsn');                            \*改变name
Query OK, 1 row affected (0.01 sec)

删除唯一约束:

mysql> alter table user8 drop index id;                                        \*在这里,MUL与id一行
Query OK, 0 rows affected (0.02 sec)

学习MySQL

4.NOT NULL非空约束

eg.建立一个在name上具有not null属性的数据表user9

mysql> create table user9(
    -> id int,
    -> name varchar(20) not null
    -> );
Query OK, 0 rows affected (0.02 sec)

NULL栏产生了标记(name不能为空):
学习MySQL
尝试添加数据:

mysql> insert into user9(id) values(1);                      \*name为空,不符合设定
ERROR 1364 (HY000):

mysql> insert into user9 values(1,'zhangsan');                                           
Query OK, 1 row affected (0.01 sec)

mysql> insert into user9(name) values('lisi');               \*id为空,不影响插入数据
Query OK, 1 row affected (0.01 sec)

学习MySQL

5.默认约束

插入字段值时,若未传值,就会使用默认值
eg.建立一个属性上具有默认约束的数据表user10

mysql> create table user10(
    -> id int,
    -> name varchar(20),
    -> age int default 10
    ->   );
Query OK, 0 rows affected (0.02 sec)
mysql> insert into user10 (id,name) values(1,'zhangsan');    \*未指定age,自动指定默认值
Query OK, 1 row affected (0.01 sec)

mysql> insert into user10 (id,name,age) values(2,'lisi',19); \*传值age,则不会用到默认值
Query OK, 1 row affected (0.01 sec)

学习MySQL

6.外键约束

  • 涉及两种表:父表、子表(主表、副表)

eg.建立两种表并进行关联
父表:

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)      \*表中的class_id属性值必须在classes表内的id
    -> );
Query OK, 0 rows affected (0.02 sec)

子表中KEY类型出现MUL:
学习MySQL
母表插入多条数据:

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> insert into students values(1001,'张三',1);
Query OK, 1 row affected (0.01 sec)

mysql> insert into students values(1002,'张三',2);
Query OK, 1 row affected (0.01 sec)

mysql> insert into students values(1003,'张三',3);
Query OK, 1 row affected (0.01 sec)

mysql> insert into students values(1004,'张三',4);
Query OK, 1 row affected (0.01 sec)

mysql>  insert into students values(1005,'lisi',5);   \*出现错误,表classes中没有id=5
ERROR 1452 (23000): Unknown error 1452

学习MySQL

  • 主表classes中没有的数据值,在副表中,是不可以使用的。
  • 若母表已经被引用,则该记录不可以被删除
    eg.
mysql> delete from calsses where id=4;              \*若主表子表被引用class_id=4,则母表的id=4不能删除
ERROR 1146 (42S02): Unknown error 1146

学习MySQL

三、数据表设计

数据库的三大设计范式
范式根据实际操作来选定

1. 第一范式(1NF)

数据表中的所有字段都是不可分割的原子值
eg.该例子中(1)的字段值还可以继续拆分,不满足第一范式
address-》cuntry | privence | city | details

mysql> create table student2(
    -> id int primary key,
    -> name varchar(20),
    -> address varchar(30)
    -> );
    
mysql>  insert into student2 values(1,'张三','中国四川省成都市武侯区武侯大道100号');
Query OK, 1 row affected (0.01 sec)

mysql>  insert into student2 values(2,'李四','中国四川省成都市武侯区京城大道200号');
Query OK, 1 row affected (0.01 sec)

mysql>  insert into student2 values(3,'李五','中国四川省成都市武侯区天府大道90号');               \*这里的address值还可以继续拆分
Query OK, 1 row affected (0.01 sec)

学习MySQL
设计的越详细,对于某些实际操作有益,但可能会增加一些复杂度
学习MySQL

2. 第二范式(2NF)

必须在满足第一范式的前提下。
第二范式要求,除主键外的每一列都必须完全依赖于主键
如果要出现不完全依赖,只可能发生在联合主键的情况下。

eg.订单表.(1)除主键以外的其他列,只依赖于主键的部分字段。

mysql>   create table myorder(
    -> product_id int,
    ->  customer_id int,
    ->  product_name varchar(20),
    -> customer_name varchar(20),
    -> primary key(product_id,customer_id)
    -> );

学习MySQL
进行拆分,以满足第二范式:

mysql>   create table myorder(
    -> product_id int,
    ->  customer_id int,
    ->  product_name varchar(20),
    -> customer_name varchar(20),
    -> primary key(product_id,customer_id)
    -> );
    
mysql>   create table myorder(
    -> order_id int  primary key
    ->  product_id int,
    -> customer_id int
   );
mysql>   create table product(
   -> id int primary key;
   -> name varchar(20),
    );

mysql>   create table customer(
   -> id int primary key;
   -> name varchar(20),
    );

3. 第三范式(3NF)

必须先满足第二范式,除开主键列的其他列之间不能有传递依赖关系。
eg.

create table myorder(
order_id int primary key,
product_id int,
customer_id int,
customer_name varchar(20);        \*customer id和name有传递依赖关系,所以该表不代表3NF
);
create table myorder(
order_id int primary key,
product_id int,
customer_id int
);
create table customer(
id int primary key,
name varchar(20),
phone varchar(15)
);

四、查询练习

eg. 学生表、课程表、成绩表、教师表
注意联合主键的位置

1.查询表(student)中的某些列(sname,ssex,class):

其它列不会显示

mysql> select sname, ssex, class from student;

2.DISTINCT查询表(student)中的某属性(class)下不重复的列

eg.查询不同班级并列出

mysql> select distinct class from student;
+-------+
| class |
+-------+
| 95033 |
| 95031 |
+-------+
2 rows in set (0.01 sec)

3. 查询表中数字在101~102间的所有记录

eg.BETWEEN 从表(student)中查询属性值(class)介于某范围(95032≤class≤95033)之间的值(在这里class的值为varchar(20)也是适用的)

mysql> select *from  student  where  class  between  95032  and  95033 ;

·还可以直接使用运算符比较(表score,参数degree为int形式,范围80≤degree≤100)

mysql>  select * from score where degree>80 and degree <100;

如果只需要显示某些属性,可以这么写:

mysql>  select sno,degree from score where degree>80 and degree <100;

4. 查询在特定属性值情况下的所有数据

eg.查询表(score)中属性(degree)为某些值(85,86,88)的结果

mysql>  select * from score where degree in(85,86,88);

5.查询表中不满足不同属性下某值的结果

eg.查询表(student)中属性1(class)和属性2(sex)为x(‘95031’) 和y (‘女’)的记录

mysql>   select *  from student where class='95031' or sex='女';

6.以某属性为准按一定顺序序查询数据表中所有记录

eg.降序查询以class属性为准的表student的数据

mysql>  select * from student order by class desc;

eg.升序:

select * from student order by class asc;

或者省略asc:

mysql>  select * from student order by class;

7.以A属性升序,B属性降序查询score表中的所有记录

eg.以属性cno升序,且degreee降序,查询表score的所有记录

mysql>  select * from score order by cno as,degree desc;

8. COUNT查询某属性下的记录个数

  • 需用到统计 count
    eg.符合统计表student中属性(class)为值A(‘95031’)的数据数
mysql>  select  count(*) from student where class='95031';

9. 查看某属性数据最值的数据信息

eg.查询表(score)中的某最值属性(degree的最大值)对应的其它属性信息(学生学号sno)和(课程号cno)

mysql> select sno,cno from score where degree=(select max(degree) from score);

该指令属于子查询(1.找到最高分 2.找最高分的sno 和cno)
·有时可能会忘记表(score)所设定的属性的类别,可以通过相应指令来查看原始代码:

mysql> show create table score;

结果:
学习MySQL

10. 排序的做法

eg. 显示表(score)中的某几个属性(sno cno degree三种)并按照某一属性(degree)的升序排列

mysql> select sno,cno,degree from score order by degree;

eg.显示倒序第一条
limit(x,y)y——查询多少条,x——从第x条开始(起始号为0)

mysql> select sno,cno,degree from score order by degree desc limit 0,1;

11. 计算表中限定条件下某属性值的平均值

eg.从表(score)中,在特定条件下(属性cno为=‘3-105’)查询属性(degree)的平均值

select avg(degree)from score where cno=‘3-105’;

12. 计算表中限定条件下某属性值的平均值(不同条件同时显示)

eg.显示在不同条件限制下(属性cno包含的所有属性值),表(score)中某属性(degreee)的平均值

mysql>select cno,avg(degree)from score group by cno’;

学习MySQL

13.查询表中特定条件的平均数

复杂问题分段操作:
eg. 找出表(score)中至少有2名学生选修,并以3开头的课程(cno)的平均分数(degree),并统计人数

mysql>select cno,avg(degree),count(*) from score group by cno
->having count (cno)>=2 and cno like 3%;

14.同时查询多个表中的某些特定属性对应的数据

eg.从多个表(student、score)中显示多属性(sname| cno,degree)对应的数据

mysql>select snme,cno,degree from student,score
->where student.sno=score.sno;                            \*有主键

eg.查询所有学生的sname属性(表student),cname属性(表course)和degree属性(表score)列
并将sname列命名为stu_name

mysql>select sname as stu_name, cname ,degree from student,course,score
->where student.sno=score.sno and course.cno=score.cno;

eg. 查询“95031”班(class限定)的学生(sno)每门课(score数据表)的分数

mysql>select * from score where sno in (select sno from student where class=‘95031’)                           \*数据表score的含有sutdent的信息
->

eg. 查询“95031”班(class限定)的学生(sno)每门课(score数据表)的平均分

select cno,avg(degree) from score where sno in (select sno from student where class=‘95031’)  group by  cno;                    

WHERE ·GROUPBY ·AVG · df·

eg.查询选修课程“3-105”的成绩高于“109“号同学"3-105"课程的所有记录

select * from score where cno='3-105' and degree> (select degree from score where sno='109' and cno='3-105');               
eg.在表(student)中查询学号(sno)为108,101的同学的出生日期(sbirthday)的年份

select year(sbirthday) from student where sno in(108,101)

eg.在表(student)中查询学号(sno)为108,101的同学的出生日期(sbirthday)的年份相同的所有人的信息
```
select * from student where year (sbirthday) in (select year(sbirthday) from student where sno in(108,101));

eg. 查询选修课某课程(cno)的同学人数多于5人的教师姓名(tname)

select cno from score group by cno having count(*)>5

select* from teacher;
select tno from course where cno  in (select cno from score group by cno having count(*)>5);

select tname from teacher in(select tno from course where tno  in (select tno from course where cno  in (select cno from score group by cno having count(*)>5));

eg.查询出“计算机系“ 和"电子工程系"且不同职称的教师的tname,prof(并集-交集)
——Union求并集

select prof from teacher where depart="电子工程系";

select* fromteacher where depart=“计算机系”and prof not in(select prof from teacher where depart="电子工程系")     \*无分号
union
select* fromteacher where depart=“电子工程系" and prof not in(select prof from teacher where depart=“计算机系”);

eg.查询选修编号为“3-105”课程且成绩 至少大于一个 选修编号为“3-245”的同学的所有信息,并按Degree从高到低次序排序

  • 至少一种\ ANY
select * from score where cno='3-105' and degree any(select degree from score where cno=‘3-245’)
->order by degree desc;

eg.找出取得课程"3-105"的成绩,高于所有选修编号“3-245”成绩的同学的所有信息

  • 且\ ALL的使用
select * from score
->where cno="3-105" 
->and degree>all(select from score where cno='345');

eg.查询教师、同学的name sex 和birthday

select tname as name,tsex as sex,tbithday as bithday from teacher
->union
->select sname ,ssex,sbirhtday from student;           \*两张表合一后表头名按照tanme,tsex,tbithday排列(第二条指令默认与第一条同),需改变名称

eg.???查询成绩<该课程平均成绩的同学的成绩表

cerate temporary table b select * from a;                                \*???????
select * from score score where degree<(select avg(degree) from score b where a.cno=b.cno);

eg.所有任课老师的tnme 和deoart

select tname depart from teacher where tno in (select tno from course);

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

select class from student where ssex='男' group by class having count(*)>1;`

eg.查询student表中不姓“王的同学记录”

  • 模糊查询 NOT LIKE 用到了正则表达式
select * from student where sname not like ''王%;                      \*   %通配符,表示任意字符,表示不是比较的重点

eg.查询student表中每个学生的姓名(sname)和年龄(表中仅有date属性)
select year(now());

  • NOW()
select snme,year(now())-year(sirthday) as ‘年龄’ from student;

eg.查询student表中最大和最小的sbirthday日期值

  • MAX MIN
select max(sbiethday) as '最大', min(sbiethday) as '最小'from student;  \*但是这里的max和min是按照数字大小排列的

学习MySQL

eg.以班号(属性class)和年龄(属性sbirthday)从大到小的顺序查询表(student)中的全部记录

select * from student order by class desc,sbirthday;                \*属性class相比sbirthday的优先级更高

eg.查询与Alice性别且同班同学的sname。

sleect * from student where 
->ssex=(select ssex from student where name=‘Alice’)
->and class=(select class from student where name=‘Alice’);

eg.查询所有选修“计算机导论”课程(course表)的“男”同学(student)的的成绩表(score)

select * fromscore
->where cno=(select cno from course where cname=‘计算机导论’)
->and sno in (slect sno from student where ssex='男');

eg.查询所有同学的sno、cno和grade

  • 新建一个表格,用来存放成绩等级
mysql> create table grade(
    -> low int(3),
    -> upp int(3),
    -> grade char(1)
    -> );
mysql> insert into grade values(90,100,'A');
Query OK, 1 row affected (0.02 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 sno cno grade from score,grade where degree between low and upp;

五、连接查询

eg.建立两张表
学习MySQL

内连接 inner join / join

学习MySQL

将多表中有关联的字段进行等值连接
(表中数据通过某个字段相对,查询出相关记录数据)

mysql>select * from person inner join card on person.cardId=card.id;
mysql>select * from person inner join card on person.cardId=card.id;     \*和上一条效果相同
![在这里插入图片描述](https://www.icode9.com/i/ll/?i=20201225204434848.png)

外连接

  1. 左连接 left join / left outer join
    学习MySQL

左外连接,会将左侧表中所有的数据提取出,而右侧数据,若相等则显示;不相等则补NULL

mysql>select * from person left join card on person.cardId=card.id;
mysql>select * from person left outer join card on person.cardId=card.id;          \*和上一条效果相同

学习MySQL

  1. 右连接 irght join right / outer join
    学习MySQL
mysql>select * from person right join card on person.cardId=card.id;
mysql>select * from person right outer join card on person.cardId=card.id;          \*和上一条效果相同

学习MySQL

  1. 完全外连接 fulll join / full outer join
    学习MySQL

mysql不支持full join

mysql>select * from person full join card on person.cardId=card.id;
mysql>select * from person full outer join card on person.cardId=card.id;          \*和上一条效果相同

ERROR 1054 (42S22): Unknown colum 'person.cardId' in 'on clause''

六、事务

mysql中,事务是一个最小的不可风格的工作单元。事务能够保证一个业务的完整性。

eg.银行转账:
a -> -100
update user set money=money-100 where name =‘a’;
b->+100
update user set money=money+100 where name =‘a’;

  • 而在实际的程序中,如果只有一条语句执行成功,而另一条没执行成功时,可能会发生问题
  • 出现数据前后不一致
    update user set money=money-100 where name =‘a’;
    update user set money=money+100 where name =‘a’;
  • 多条sql语句,可能会有同时成功的要求,要么就同时失败。

事务的四大特征:
A. 原子性:事务是最小的单位,不可再分
C. 一致性:食物要求 ,同一事物中的sql语句,必须同时保证同时成功或者同时失败。
I. 隔离性:事务1 和 事务2 之间是具有隔离性的。
D. 持久性:事务一旦结束(commit,rollback),就不可返回

MYSQL如何控制事务

建立一个表格:
学习MySQL

       1.mysql默认是开启事务(自动提交)
mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            1 |
+--------------+
1 row in set (0.01 sec)
  • 作用:当执行一个sql语句时,效果会立即体现出来,且不可回滚
    回滚:ROLLBACK
mysql> rollback;
Query OK, 0 rows affected (0.01 sec)

而进行该操作之后表并未产生变化(插入操作并未撤销)
学习MySQL
而关闭mysql的自动提交(AUYOCOMMIT=0)后:

mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            0 |
+--------------+
1 row in set (0.00 sec)

再次添加数据并使用ROLLBACK:
添加数据的操作(其实未提交,是临时效果)被撤销,提供了返回的机会:学习MySQL
若需要保留数据,在insert完成后使用COMMIT:

mysql> commit;

再次使用rollback,结果不变(持久性)
学习MySQL
再次调回commit=1,自动提交

(1)手动开启事务后的信息撤回:采用 BEGIN可以使rollback生效

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.00 sec)

mysql> update user set money=money+100 where name='b';
Query OK, 1 row affected (0.00 sec)

mysql> rollback;
Query OK, 0 rows affected (0.01 sec)

撤回前后:
学习MySQL

(2)手动开启事务后的信息撤回:采用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.00 sec)

mysql> update user set money=money+100 where name='b';
Query OK, 1 row affected (0.00 sec)
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

但若在rollback使用前输入commit,则不会触发rollback效果

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

事务的隔离性

1. read uncommitted;读未提交的

  • 若在两个不同地方,都在进行操作,若事务a开启之后,它的数据可以被其他事物读取到 这样会出现——脏读

  • 脏读:一个事务读到了另外一个事务未提交的数据,就叫脏读,这在实际开发中是不允许出现的。

如果有事务a和事务b:

(1)a事务对数据进行操作,在操作的过程中,事务没有被提交,但b可以看到a的操作结果

·查看数据库的隔离级别?

  • 对于mysql 8.0:
mysql>select @@global.transaction_isolation;
mysql> select @@transaction_isolation;
  • 对于mysql 5.x:
mysql> @@global.transaction_isolation;
mysql> @@tx_isolation;

默认隔离级别:

学习MySQL

·修改数据库的隔离级别

set global transaction isolation level read uncommitted;

随后隔离性变为READ-UNCOMMITTED:

mysql>  select @@global.transaction_isolation;
+--------------------------------+
| @@global.transaction_isolation |
+--------------------------------+
| READ-UNCOMMITTED               |
+--------------------------------+
1 row in set (0.00 sec)

eg.转账:小明在淘宝店买商品:800元
小明→成都 ATM
淘宝店→ 广州AMT

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> update user set money=money-800 where name='小明';
Query OK, 1 row affected (0.00 sec)

mysql>  update user set money=money+800 where name='淘宝店';
Query OK, 1 row affected (0.00 sec)

mysql> rollback;                                \*而另一方进行rollback操作,则钱没了
Query OK, 0 rows affected (0.00 sec)

2. read committed;读已提交的

  • 将系统转为read committed模式
mysql> set global transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)

学习MySQL

 事务a和事务b同时操作一张表,事务a提交的数据,不能被事务b读取到,就会造成幻读。

eg.两方共同使用数据库,虽然只能读到提交的数据,但还是会出现问题:另一方发现前后不一致

3. repeatable read; 可以重复读

eg.两方共用一个数据,前后插入信息并提交:

A:

mysql> start transaction;
Query OK, 0 rows affected (0.00 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)

B:

mysql>insert into user values(6,'d',1000);
ERROR 1062(23000):Duplicate entry '6' for key 'primary';                  \*出现幻读现象

4. serializable;单行化

串行化带来的问题:性能差

set global transaction isolation level serializable;
select @@global.transaction_isolation;

学习MySQL
eg.两方共用一个数据,前后插入信息并提交:

A:

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql>insert into user values(7,'f',100);
Query OK, 1 row affected (0.01 sec)
mysql> commit;
Query OK, 0 rows affected (0.01 sec)

B:

mysql> select * from user;                        \*看到了A更新后的表格
mysql>insert into user values(8,'oo',1000);



                                                            \命令执行时卡住

操作串行化,两端不可同时进行写入操作,进入等待状态
A提交数据
A:

commit;

B立刻弹出结果
B:

Query OK, 1 row affected (7.76 sec)                                \*等待commit后

若超时则会弹出。此时B端需要重新插入:

ERROR 1064(4200):you have an error in your SQL
syntax; check the manual that corresponds to your mysql server version fo the righr syntax to use near 'mysql'     \*超时

mysql>insert into user values(8,'oo',1000);
Query OK, 1 row affected (0.01 sec)                                
  • 当表user被另外一个实务操作时,其它事务中的写作错做,是不可以进行的。
  • 进入排队状态(串行化),直到A事务结束之后,B的写入操作才能被执行(但需要再没有等待超时的情况下)
性能对比 > 隔离级别高, 性能减弱(问题多)
READ-UNCIMMUTTED READ-COMMITTED REPEATABLE-READ SWRIALIZABLE

课程来自一天学会MySQL数据库?

上一篇:MySQL数据库(二):列类型和数据完整性


下一篇:Mybatis使用Map当做参数获取插入数据成功后返回的自增id