目录
数据库介绍
数据库基本概念
数据库类型
MySql数据库管理系统
SQL语言
概述
常见操作
表的完整性约束
非外键约束
外键约束
单表查询
函数
多表查询
事务
事务隔离级别
视图
数据库介绍
数据库基本概念
数据:所谓数据(Data)是指对客观事物进行描述并可以鉴别的符号,这些符号是可识别的、抽象的。它不仅仅指狭义上的数字,而是有多种表现形式:字母、文字、文本、图形、音频、视频等。现在计算机存储和处理的数据范围十分广泛,而描述这些数据的符号也变得越来越复杂了。
数据库:数据库(Database,DB)指的是以一定格式存放、能够实现多个用户共享、与应用程序彼此独立的数据集合。
数据库管理系统:数据库管理系统(Database Management System,DBMS)是用来定义和管理数据的软件。如何科学的组织和存储数据,如何高效的获取和维护数据,如何保证数据的安全性和完整性,这些都需要靠数据库管理系统完成。目前,比较流行的数据库管理系统有:Oracle、MySQL、SQL Server、DB2等。
数据库应用程序:数据库应用程序(Database Application System,DBAS)是在数据库管理系统基础上,使用数据库管理系统的语法,开发的直接面对最终用户的应用程序,如学生管理系统、人事管理系统、图书管理系统等。
数据库系统:数据库系统(Database System,DBS)一般是由数据库、数据库管理系统、数据库应用程序、数据库管理员和最终用户构成。其中DBMS是数据库系统的基础和核心。
数据库类型
- 关系型数据库 :将复杂的数据结构用较为简单的二元关系(二维表)来表示。在该类型数据库中,对数据的操作基本上都建立在一个或多个表格上,我们可以采用结构化查询语言(SQL)对数据库进行操作。关系型数据库是目前主流的数据库技术,其中具有代表性的数据库管理系统有:Oracle、DB2、SQL Server、MySQL等。
- 非关系型数据库(NOSQL):NOSQL(Not Only SQL)泛指非关系型数据库。关系型数据库在超大规模和高并发的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题。NOSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。常见的非关系型数据库管理系统有Memcached、MongoDB,redis,HBase等。
关系型数据库是存储在硬盘上,而非关系型数据库是存储在硬盘,访问速度更快。
MySql数据库管理系统
理ilnaug概述:MySQL是一种开放源代码的轻量级关系型数据库,MySQL数据库使用最常用的结构化查询语言(SQL)对数据库进行管理;MySQL数据库体积小、速度快、成本低、开放源码等优点。
安装好数据库后可以在对应bin目录下cmd登陆mysql。
或者配置环境变量后,直接在cmd登陆。
登陆所用参数:
-h:host主机名。后面跟要访问的数据库服务器的地址;如果是登录本机,可以省略
-u:user 用户名。后面跟登录数据的用户名,第一次安装后以root用户来登录,是MySQL的管理员用户
-p: password 密码。一般不直接输入,而是回车后以保密方式输入。
MySQL 层次:不同项目对应不同的数据库组成 - 每个数据库中有很多表 - 每个表中有很多数据
退出数据库:可以使用quit或者exit命令完成,也可以用\q; 完成退出操作 。
数据库的卸载:在服务中停止mysql服务,然后再控制面板中卸载mysql软件。删除所有的mysql文件夹。(C:\Program Files\MySQL;C:\ProgramData\MySQL。);把环境变量删除。
SQL语言
概述
数据库管理人员(DBA)通过数据库管理系统(DBMS)可以对数据库(DB)中的数据进行操作,操作用到的就是sq语言。
SQL(Structured Query Language)是结构化查询语言的简称,它是一种数据库查询和程序设计语言,同时也是目前使用最广泛的关系型数据库操作语言。在数据库管理系统中,使用SQL语言来实现数据的存取、查询、更新等功能。
- SQL语言可以分为五个部分:
- 数据查询语言(Data Query Language,DQL):DQL主要用于数据的查询,其基本结构是使用SELECT子句,FROM子句和WHERE子句的组合来查询一条或多条数据。
- 数据操作语言(Data Manipulation Language,DML):DML主要用于对数据库中的数据进行增加、修改和删除的操作,其主要包括:INSERT:增加数据、 UPDATE:修改数据、DELETE:删除数据
- 数据定义语言(Data Definition Language,DDL):DDL主要用针对是数据库对象(数据库、表、索引、视图、触发器、存储过程、函数)进行创建、修改和删除操作。其主要包括:CREATE:创建数据库对象、ALTER:修改数据库对象、DROP:删除数据库对象
- 数据控制语言(Data Control Language,DCL):DCL用来授予或回收访问 数据库的权限,其主要包括: GRANT:授予用户某种权限、REVOKE:回收授予的某种权限
- 事务控制语言(Transaction Control Language,TCL):TCL用于数据库的事务管理。其主要包括:START TRANSACTION:开启事务、COMMIT:提交事务、ROLLBACK:回滚事务、SET TRANSACTION:设置事务的属性 。
常见操作
创建数据库表:
-- 创建数据库表:
create table t_student(
sno int(6), -- 6显示长度
sname varchar(5), -- 5个字符
sex char(1),
age int(3),
enterdate date,
classname varchar(10),
email varchar(15)
);
-- 查看表的结构:展示表的字段详细信息
desc t_student;
-- 查看表中数据:
select * from t_student;
-- 查看建表语句:
show create table t_student;
对于数据库表的字段类型:
- 整数类型:
在int类型后的括号里面可以加数字,指定显示的整数长度,但并不会限制大小
主键自增:不使用序列,通过auto_increment,要求是整数类型
- 浮点数类型
需要注意的是与整数类型不一样的是,浮点数类型的宽度不会自动扩充。double(4,1)--小数部分为1位,总宽度4位,并且不会自动扩充。
- 字符串类型
CHAR和VARCHAR类型相似,均用于存于较短的字符串,主要的不同之处在于存储方式。CHAR类型长度固定,VARCHAR类型的长度可变。
因为VARCHAR类型能够根据字符串的实际长度来动态改变所占字节的大小,所以在不能明确该字段具体需要多少字符时推荐使用VARCHAR类型,这样可以大大地节约磁盘空间、提高存储效率。
CHAR和VARCHAR表示的是字符的个数,而不是字节的个数
- 日期和时间类型
TIMESTEMP类型的数据指定方式与DATETIME基本相同,两者的不同之处在于以下几点:
(1) 数据的取值范围不同,TIMESTEMP类型的取值范围更小。
(2) 如果我们对TIMESTAMP类型的字段没有明确赋值,或是被赋与了NULL值,MySQL会自动将该字段赋值为系统当前的日期与时间。
(3) TIMESTEMP类型还可以使用CURRENT_TIMESTAMP来获取系统当前时间。now() , sysdate() ,也可以显示获得当前时间。
(4) TIMESTEMP类型有一个很大的特点,那就是时间是根据时区来显示的。例如,在东八区插入的TIMESTEMP数据为2017-07-11 16:43:25,在东七区显示时,时间部分就变成了15:43:25,在东九区显示时,时间部分就变成了17:43:25。
在创建好数据库之后我们就开始插入数据。
格式:insert into 表名 values()——>这是在所有字段插入的情况
insert into 表名 (字段名) values()——>插入其中某几个字段
可以在一个insert后面添加多条数据:insert into 表名 values (),(),();
注意事项:
- int 宽度是显示宽度,如果超过,可以自动增大宽度 int底层都是4个字节
- 时间的方式多样 '1256-12-23' "1256/12/23" "1256.12.23"
- 字符串不区分单引号和双引号
- 如何写入当前的时间 now() , sysdate() , CURRENT_DATE()
- char varchar 是字符的个数,不是字节的个数,可以使用binary,varbinary表示定长和不定长的字节个数。超过长度会报错,不会自动增加宽度。
修改数据
update 表名 set 字段名="";——>这种操作会将表中的所有数据都会更改
update 表名 set 字段名="" where 条件;——>这种操作将会修改符号条件的数据
删除数据
delete from 表名;会删除整个表数据
delete from 表名 where 字段=“”;会删除对于条件的数据
注意事项
1.关键字,表名,字段名不区分大小写
2.默认情况下,内容不区分大小写
3.删除操作from关键字不可缺少
4.修改,删除数据别忘记加限制条件
修改、删除数据库表
修改表的结构:
- -- 增加一列:alter table 表名 add 字段名 字段类型 ;
- -- 增加一列(放在最前面)alter table 表名 add 字段名 字段类型 first;
- -- 增加一列(放在xx列的后面)alter table 表名 add 字段名 字段类型 after xx;
- -- 删除一列:alter table 表名 drop 字段名
- -- 修改一列:
- alter table t_student modify score float(4,1); -- modify修改是列的类型的定义,但是不会改变列的名字
- alter table t_student change score score1 double(5,1); -- change修改列名和列的类型的定义
- -- 删除表:drop table 表名;
表的完整性约束
非外键约束
为防止不符合规范的数据存入数据库,在用户对数据进行插入、修改、删除等操作时,MySQL提供了一种机制来检查数据库中的数据是否满足规定的条件,以保证数据库中数据的准确性和一致性,这种机制就是完整性约束。
注意:
- 如果sql报错,可能主键就浪费了,后续插入的主键是不连号的,我们主键也不要求连号的
- 如果主键没有设定值,或者用null.default都可以完成主键自增的效果
约束从作用上可以分为两类:
(1) 表级约束:可以约束表中任意一个或多个字段。与列定义相互独立,不包含在列定义中;与定义用‘,’分隔;必须指出要约束的列的名称;
(2) 列级约束:包含在列定义中,直接跟在该列的其它定义之后 ,用空格分隔;不必指定列名;
20.-- 在创建表以后添加约束:
21.alter table t_student add constraint pk_stu primary key (sno) ; -- 主键约束
22.alter table t_student modify sno int(6) auto_increment; -- 修改自增条件
23.alter table t_student add constraint ck_stu_sex check (sex = '男' || sex = '女');
24.alter table t_student add constraint ck_stu_age check (age >= 18 and age <= 50);
25.alter table t_student add constraint uq_stu_email unique (email);
总结:
1.主键约束
主键约束(PRIMARY KEY,缩写PK),是数据库中最重要的一种约束,其作用是约束表中的某个字段可以唯一标识一条记录。因此,使用主键约束可以快速查找表中的记录。就像人的身份证、学生的学号等等,设置为主键的字段取值不能重复(唯一),也不能为空(非空),否则无法唯一标识一条记录。
主键可以是单个字段,也可以是多个字段组合。对于单字段主键的添加可使用表级约束,也可以使用列级约束;而对于多字段主键的添加只能使用表级约束。
2.非空约束
非空约束(NOT NULL,缩写NK)规定了一张表中指定的某个字段的值不能为空(NULL)。设置了非空约束的字段,在插入的数据为NULL时,数据库会提示错误,导致数据无法插入。
无论是单个字段还是多个字段非空约束的添加只能使用列级约束(非空约束无表级约束)
为已存在表中的字段添加非空约束
alter table student8 modify stu_sex varchar(1) not null; |
使用ALTER TABLE语句删除非空约束
alter table student8 modify stu_sex varchar(1) null; |
3. 唯一约束
唯一约束(UNIQUE,缩写UK)比较简单,它规定了一张表中指定的某个字段的值不能重复,即这一字段的每个值都是唯一的。如果想要某个字段的值不重复,那么就可以为该字段添加为唯一约束。
无论单个字段还是多个字段唯一约束的添加均可使用列级约束和表级约束
4. 检查约束
检查约束(CHECK)用来限制某个字段的取值范围,可以定义为列级约束,也可以定义为表级约束。MySQL8开始支持检查约束。
5. 默认值约束
默认值约束(DEFAULT)用来规定字段的默认值。如果某个被设置为DEFAULT约束的字段没插入具体值,那么该字段的值将会被默认值填充。
默认值约束的设置与非空约束一样,也只能使用列级约束。
6. 字段值自动增加约束
自增约束(AUTO_INCREMENT)可以使表中某个字段的值自动增加。一张表中只能有一个自增长字段,并且该字段必须定义了约束(该约束可以是主键约束、唯一约束以及外键约束),如果自增字段没有定义约束,数据库则会提示“Incorrect table definition; there can be only one auto column and it must be defined as a key”错误。
由于自增约束会自动生成唯一的ID,所以自增约束通常会配合主键使用,并且只适用于整数类型。一般情况下,设置为自增约束字段的值会从1开始,每增加一条记录,该字段的值加1。
/*为student11表中的主键字段添加自增约束*/
alter table student11 modify stu_id int(10) auto_increment;
使用ALTER TABLE语句删除自增约束
alter table studen11 modify stu_id int(10);
外键约束
概述:
外键约束(FOREIGN KEY,缩写FK)是用来实现数据库表的参照完整性的。外键约束可以使两张表紧密的结合起来,特别是针对修改或者删除的级联操作时,会保证数据的完整性。
外键是指表中某个字段的值依赖于另一张表中某个字段的值,而被依赖的字段必须具有主键约束或者唯一约束。被依赖的表我们通常称之为父表或者主表,设置外键约束的表称为子表或者从表。
- 创建的时候先创建父表,再创建子表
- 删除的时候先删除子表,再删除父表
外键约束只有表级约束,没有列级约束
格式: constraint fk_stu_classno foreign key (字段名) references 父表名 (父表字段)
在创建表以后添加外键约束:alter table 表名 add constraint fk_stu_classno foreign key (classno) references t_class (cno)
外键策略:
如果我们直接删除父表元素会报错,因为i有子表依赖;
策略1:no action不允许操作;就是把子表依赖的删除或者修改,然后可以删除父表中没有依赖的字段。
策略2:cascade 级联操作:操作主表的时候影响从表的外键信息。
- 先删除之前的外键约束:
- alter table t_student drop foreign key fk_stu_classno;
- -- 重新添加外键约束:
- alter table t_student add constraint fk_stu_classno foreign key (classno) references t_class (cno) on update cascade on delete cascade;
策略2就是在删除父表对于字段时候依赖于该字段的数据也会被删除,更高该字段时依赖的数据也会更改。
策略3:set null 置空操作:
- -- 先删除之前的外键约束:
- alter table t_student drop foreign key 外键名;
- -- 重新添加外键约束:
- alter table t_student add constraint fk_stu_classno foreign key (classno) references t_class (cno) on update set null on delete set null;
注意:策略2和策略3是可以混着使用的
DDL和DML补充:
快速添加一张和xx一样的表:
- create table t_student2 as select * from xx;(包括表的数据和字段)
- create table t_student2 as select * from xx where 1=2;(只包括表的字段不包括任何数据)
- create table t_student4 as select sno,sname,age from t_student where sno = 2;(只包括表的某些字段和数据)
清空数据操作:
- delete from t_student;
- truncate table t_student;
delete和truncate的区别:
从最终的结果来看,虽然使用TRUNCATE操作和使用DELETE操作都可以删除表中的全部记录,但是两者还是有很多区别的,其区别主要体现在以下几个方面:
(1)DELETE为数据操作语言DML;TRUNCATE为数据定义语言DDL。
(2) DELETE操作是将表中所有记录一条一条删除直到删除完;TRUNCATE操作则是保留了表的结构,重新创建了这个表,所有的状态都相当于新表。因此,TRUNCATE操作的效率更高。
(3)DELETE操作可以回滚;TRUNCATE操作会导致隐式提交,因此不能回滚(在第十章中会讲解事务的提交和回滚)。
(4)DELETE操作执行成功后会返回已删除的行数(如删除4行记录,则会显示“Affected rows:4”);截断操作不会返回已删除的行量,结果通常是“Affected rows:0”。DELETE操作删除表中记录后,再次向表中添加新记录时,对于设置有自增约束字段的值会从删除前表中该字段的最大值加1开始自增;TRUNCATE操作则会重新从1开始自增。
单表查询
select * from 表名; 从该表查询所有数据
select 字段 from 表名; 从该表查询该字段,字段之间用逗号隔开
显示部分行:where子句
select empno,ename,job,mgr from emp where sal > 2000;显示部分列,部分行:
起别名:
- select empno 员工编号,ename 姓名,sal 工资 from emp; -- as 省略,''或者""省略了
- -- as alias 别名
- select empno as 员工编号,ename as 姓名,sal as 工资 from emp;
- select empno as '员工编号',ename as "姓名",sal as 工资 from emp;
- 在别名中有特殊符号的时候,''或者""不可以省略不写
- 算术运算符:
- select empno,ename,sal,sal+1000 as '涨薪后',deptno from emp where sal < 2500;
- select empno,ename,sal,comm,sal+comm from emp; -- ???查询时候不仅仅可以在已有字段查询,也可以查询对其操作后的数据;但是在相加的时候若其中一个伪null,则结果是null
- -- 去重操作:
- select job from emp;
- select distinct job from emp;
- select job,deptno from emp;
- select distinct job,deptno from emp; 在字段前面加上distinct对后面的所有列组合 去重 ,而不是单独的某一列去重
- -- 排序:
- select * from emp order by sal; -- 默认情况下是按照升序排列的
- select * from emp order by sal asc; -- asc 升序,可以默认不写
- select * from emp order by sal desc; -- desc 降序
- select * from emp order by sal asc ,deptno desc; -- 在工资升序的情况下,deptno按照降序排列(就是首先按照工资升序排序,然后在工资相同的情况下deptno按降序排列)
where子句
where子句:将过滤条件放在where子句的后面,可以筛选/过滤出我们想要的符合条件的数据:
-- where 子句 + 关系运算符
select * from emp where deptno = 10;
select * from emp where deptno > 10;
select * from emp where deptno >= 10;
select * from emp where deptno < 10;
select * from emp where deptno <= 10;
select * from emp where deptno <> 10;
select * from emp where deptno != 10;
select * from emp where job = 'CLERK';
select * from emp where job = 'clerk'; -- 默认情况下不区分大小写
select * from emp where binary job = 'clerk'; -- binary区分大小写
select * from emp where hiredate < '1981-12-25';-- 对日期也可以比较
-- where 子句 + 逻辑运算符:and
select * from emp where sal > 1500 and sal < 3000; -- (1500,3000)
select * from emp where sal > 1500 && sal < 3000;
select * from emp where sal > 1500 and sal < 3000 order by sal;
select * from emp where sal between 1500 and 3000; -- [1500,3000]注意between……and是闭合的
where 子句 + 逻辑运算符:or
select * from emp where deptno = 10 or deptno = 20;
select * from emp where deptno = 10 || deptno = 20;
select * from emp where deptno in (10,20);-- 选择是10或者20的结果
select * from emp where job in ('MANAGER','CLERK','ANALYST');
-- where子句 + 模糊查询:
-- 查询名字中带A的员工 -- %代表通配符
select * from emp where ename like '%A%' ;
-- -任意一个字符
select * from emp where ename like '_A%' ;-- 下划线表示的是一个字符
-- 关于null的判断:
select * from emp where comm is null;
select * from emp where comm is not null;
-- 小括号的使用 :因为不同的运算符的优先级别不同,加括号为了可读性
select * from emp where job = 'SALESMAN' or job = 'CLERK' and sal >=1500; -- 先and再or 优先级: and > or
select * from emp where job = 'SALESMAN' or (job = 'CLERK' and sal >=1500);
select * from emp where (job = 'SALESMAN' or job = 'CLERK') and sal >=1500;
函数
MySQL中提供了大量函数来简化用户对数据库的操作,比如字符串的处理、日期的运算、数值的运算等等。使用函数可以大大提高SELECT语句操作数据库的能力,同时也给数据的转换和处理提供了方便。 (在sql中使用函数)函数提高了select能力
函数只是对查询结果中的数据进行处理,不会改变数据库中数据表的值。MySQL中的函数主要分为单行函数和多行函数两大类。(单行多行可以根据对其操作的数据进行判断,如果该函数操作的是多行数据eg:求最大值、最小、和等等就是多行函数,对一行数据进行处理就是单行函数)
除了多行函数都是单行函数
单行函数
字符串函数
数值函数
日期与时间函数
注意:
- substring下标是从1开始往后数
select abs(-5),ceil(5.3),floor(5.9),round(3.14) from dual; -- dual实际就是一个伪表,也可以省略不写
curdate()是年月日,curtime()是时分秒;now()、sysdate()是年月日时分秒;但是当擦插入数据时候会参照表的结构的
流程函数
其他函数
- select empno,ename,sal,if(sal>=2500,'高薪','底薪') as '薪资等级' from emp; -- if-else 双分支结构
- select empno,ename,sal,comm,sal+ifnull(comm,0) from emp; -- 如果comm是null,那么取值为0 -- 单分支
case job
when 'CLERK' then '店员'
when 'SALESMAN' then '销售'
when 'MANAGER' then '经理'
else '其他'
end '岗位',
sal from emp;
注意:在查询多个字段时不同字段之间用逗号隔开,而和as 类似的重命名是空格
多行函数
- 多行函数会自动忽略null值,而0不会忽略
- max(),min(),count()针对所有类型 sum(),avg() 只针对数值型类型有效
- count计数:select count(*) from 表名;select 1 from 表名;直接使用某个字段不一定准确,因为count()不会统计null的个数。
group_by(用来分组)
当我们同时查询多行函数和某一个字段时候是不会出现预期结果,我们不能这么使用;通长我们可以先分组再求其多行函数。
- select deptno,avg(sal) from emp group by deptno; -- 字段和多行函数不可以同时使用,除非这个字段属于分组
- select deptno,avg(sal) from emp group by deptno order by deptno desc;
having 分组后进行筛选
- select deptno,avg(sal) 平均工资 from emp group by deptno having 平均工资 > 2000 order by deptno desc;
有两种方法,可以先进行筛选再进行分组;或者先进行分组再进行筛选
select 字段名1,avg(字段名) from 表名 where 字段名条件 group by 字段名1
select 字段名1,avg(字段名) from 表名 group by 字段名1 having 字段名条件
having where order by后面都是加字段名,实现对其筛选或者按照某种规则排列输出。
单表查询语句总结:
select column, group_function(column)
from table
[where condition]
[group by group_by_expression]
[having group_condition]
[order by column];
注意:顺序固定,不可以改变顺序
select语句的执行顺序:from--where -- group by– select - having- order by
多表查询
实际开发中往往需要针对两张甚至更多张数据表进行操作,而这多张表之间需要使用主键和外键关联在一起,然后使用连接查询来查询多张表中满足要求的数据记录。
一条SQL语句查询多个表,得到一个结果,包含多个表的数据。效率高。在SQL99中,连接查询需要使用join关键字实现。
提供了多种连接查询的类型: cross natural using on
交叉连接(CROSS JOIN)是对两个或者多个表进行笛卡儿积操作,所谓笛卡儿积就是关系代数里的一个概念,表示两个表中的每一行数据任意组合的结果。比如:有两个表,左表有m条数据记录,x个字段,右表有n条数据记录,y个字段,则执行交叉连接后将返回m*n条数据记录,x+y个字段
- 交叉连接cross join:select * from 表名 cross join 表名(在mysql中cross是可以省略不写的)
- 自然连接natural join :它可以自动匹配所有的同名列,同名列只展示一次 。:select * from 表名 natural join 表名;但是这种方法并没有指定查询字段所在表,查询速度慢、效率低
- 给字段名指定表 select e.empno,e.ename,e.sal,d.dname,d.loc,d.deptno from emp e natural join dept d;
- 在自然连接中他会自动匹配所有的同名字段,如果我们只想匹配部分字段,可以使用内连接
select * from emp e inner join dept d using(deptno) -- 这里不能写natural join了 ,这里是内连接,可以指定重名字段匹配
- select * from emp e inner join dept d on (e.deptno = d.deptno);这里两个表中即使字段名不一样也可以匹配
- 可以在后面继续使用where子句进行一个筛选
- 在上面讲的连接方式中,如果连接要看的字段没有数据那么就不会在结果中显示,此时我们可以使用外连接的方式
- 左外连接: left outer join -- 左面的那个表的信息,即使不匹配也可以查看出效果select * from emp e left outer join dept d on e.deptno = d.deptno;
- 右外连接: right outer join -- 右面的那个表的信息,即使不匹配也可以查看出效果select * from emp e right outer join dept d on e.deptno = d.deptno;
- 在mysql中不支持全外连接,只能通过求并集的方式
select * from emp e left outer join dept d on e.deptno = d.deptno union select * from emp e right outer join dept d on e.deptno = d.deptno;这种方法去重,效率低
select * from emp e left outer join dept d on e.deptno = d.deptno union all select * from emp e right outer join dept d on e.deptno = d.deptno;这种方法不会去重,效率高。
其中outer可以省略不写,在mysql中只支持并集,交集和差集都不支持。
三表连接查询
思路:就是先查两个,然后把这个两个整体当作一个再与第三个表进行查询。
eg: select e.ename,e.sal,e.empno,e.deptno,d.dname,s.* from emp e right outer join dept d on e.deptno = d.deptno inner join salgrade s on e.sal between s.losal and s.hisal
自连接查询:就是把自己表看作是两张表,然后按上述方法对其操作。
不相关子查询
不相关的子查询:子查询可以独立运行,先运行子查询,再运行外查询。
子查询就是一条SQL语句有多个select语句。可以看作是select的嵌套。
单行子查询:就是在后面where子句中的查询结果只有一个
select ename,sal from emp where deptno = (select deptno from emp where ename 'CLARK') and sal < (select sal from emp where ename = 'CLARK')
多行子查询
就是在后面的查询语句结果中有多个值,如果要是有其中一个可以使用in,如果比所有的都大,可以使用all;如果比其中一个大就行可以使用any
相关子查询:子查询不可以独立运行,并且先运行外查询,再运行子查询。
好处:简单 功能强大(一些使用不相关子查询不能实现或者实现繁琐的子查询,可以使用相关子查询实现)
缺点:稍难理解
- select * from emp e where sal = (select max(sal) from emp where deptno = e.deptno) order by deptno
- select * from emp e where sal >= (select avg(sal) from emp e2 where e2.job = e.job)
事务
事务:
事务(Transaction)指的是一个操作序列,该操作序列中的多个操作要么都做,要么都不做,是一个不可分割的工作单位,是数据库环境中的逻辑工作单位,由DBMS(数据库管理系统)中的事务管理子系统负责事务的处理。
事务特性:
事务处理可以确保除非事务性序列内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的序列,可以简化错误恢复并使应用程序更加可靠。
但并不是所有的操作序列都可以称为事务,这是因为一个操作序列要成为事务,必须满足事务的原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。这四个特性简称为ACID特性。
- -- 手动开启事务:
- start transaction;
- update account set balance = balance - 200 where id = 1;
- update account set balance = balance + 200 where id = 2;
- -- 手动回滚:刚才执行的操作全部取消:
- rollback;
- -- 手动提交:
- commit;
- -- 在回滚和提交之前,数据库中的数据都是操作的缓存中的数据,而不是数据库的真实数据
事务并发问题
脏读(Dirty read)
当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的。
不可重复读
(Unrepeatableread): 指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。
幻读
(Phantom read): 幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。
不可重复度和幻读区别:
不可重复读的重点是修改,幻读的重点在于新增或者删除。
解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表
事务隔离级别
事务的隔离级别用于决定如何控制并发用户读写数据的操作。数据库是允许多用户并发访问的,如果多个用户同时开启事务并对同一数据进行读写操作的话,有可能会出现脏读、不可重复读和幻读问题,所以MySQL中提供了四种隔离级别来解决上述问题。
事务的隔离级别从低到高依次为READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ以及SERIALIZABLE,隔离级别越低,越能支持高并发的数据库操作。
- -- 查看默认的事务隔离级别 MySQL默认的是repeatable read
- select @@transaction_isolation;
- -- 设置事务的隔离级别 (设置当前会话的隔离级别)
- set session transaction isolation level read uncommitted;
- set session transaction isolation level read committed;
- set session transaction isolation level repeatable read;
- set session transaction isolation level serializable;
- start transaction ;
- select * from account where id = 1;
视图
概述:
视图(view)是一个从单张或多张基础数据表或其他视图中构建出来的虚拟表。同基础表一样,视图中也包含了一系列带有名称的列和行数据,但是数据库中只是存放视图的定义,也就是动态检索数据的查询语句,而并不存放视图中的数据,这些数据依旧存放于构建视图的基础表中,只有当用户使用视图时才去数据库请求相对应的数据,即视图中的数据是在引用视图时动态生成的。因此视图中的数据依赖于构建视图的基础表,如果基本表中的数据发生了变化,视图中相应的数据也会跟着改变。
PS:视图本质上就是:一个查询语句,是一个虚拟的表,不存在的表,你查看视图,其实就是查看视图对应的sql语句