命令行中通过命令mysql -h localhost -u 用户名 -p
回车后再输入密码进入mysql数据库,输入help
或\h
查看帮助信息,输入\c
清除前面的命令。MySQL的相关命令可以用;
、\g
或\G
表示结束。可以用delimiter $$
把结束符由;
改为$$
,再用delimiter ;
把结束符由$$
改回;
。
MySQL 在 Windows 下不区分大小写,但在 Linux 下默认是区分大小写。
一、MySQL数据库基本操作
MySQL软件中数据库可以分为系统数据库和用户数据库两大类。
数据库是存储数据库对象的容器,数据库对象是指存储、管理和使用数据的不同结构形式,主要包含表、视图、存储过程、函数、触发器和事件等。
- 创建数据库:
create database 数据库名;
- 查看数据库:
show databases;
- 选择数据库:
use 数据库名;
,出现"Database changed"表示选择数据库成功 - 删除数据库:
drop database 数据库名;
二、存储引擎和数据类型
1. 存储引擎
存储引擎指定了表的类型,即如何存储和索引数据、是否支持事务等,此外还决定了表在计算机中的存储方式。
- 查看支持的存储引擎:
show engines;
,默认为InnoDB存储引擎
2. 数据类型
数据类型主要包括:整数类型(tinyint/int/bigint等)、浮点数类型(float/double)、定点数类型(dec(M,D)/decimal(M,D))、位类型(bit(M), M$\leq$8)、日期和时间类型(date/time/datetime/timestamp/year)、字符串类型(char/varchar/text/binary/varbinary/blob)等。
将浮点数插入整形表会被截断,但不报错。
dec(M,D)表示共M位,小数点后保存D位。
如果要精确到小数点后10位以上,就要选择double类型而不是float类型。如果小数数据精度要求非常高时,则可以选择而定点数类型,比double类型精度还高。
float和double保存的是近似值,而decimal存储的是字符串。
date是年月日,time是时分秒,datetime是年月日时分秒,timestamp是当前时间戳,year是年份。
varchar的长度是可变的。binary可以存储二进制数据(图片、音乐或视频文件),varbinary只能存储字符数据。如果要存储大量二进制数据,则可以选择blob系列字符串类型。
如果插入的字符串长度超过字符串定义的长度,则会被截断,并显示警告信息。
三、表的操作
表是包含数据库中所有数据的数据库对象,其中每一行表示一条唯一的记录,每一列表示记录中的一个字段。
表中的数据对象包括列、索引、触发器
- 列:也称属性列,在创建表时必须指定列的名字和数据类型
- 索引:根据指定的列建立起来的顺序,提供了快速访问数据的途径
- 触发器:用户定义的事务命令的集合,当对一个表中的数据进行插入、更新或删除时这组命令就会自动执行
表的操作
- 创建表:
create table 表名(
属性名 数据类型,
...,
属性名 数据类型
);
- 查看表的定义:
describe 表名;
或desc 表名;
- 删除表:
drop talbe 表名;
- 修改表名:
alter table 旧表名 rename 新表名;
- 在末位增加字段:
alter talbe 表名 add 属性名 数据类型;
- 在首位增加字段:
alter talbe 表名 add 属性名 数据类型 first;
- 在指定字段后增加字段:
alter table 表名 add 属性名 数据类型 after 属性名;
- 删除字段:
alter table 表名 drop 属性名;
- 修改字段的数据类型:
alter table 表名 modify 属性名 数据类型;
- 修改字段名:
alter table 表名 change 旧属性名 新属性名 旧数据类型;
- 同时修改字段名和属性:
alter table 表名 change 旧属性名 新属性名 新数据类型;
- 修改字段顺序:
alter table 表名 modify 属性名1 数据类型 first|after 属性名2;
,将属性1移动到首位或属性2之后
表的约束
完整性是指数据的准确性和一致性,完整性检查是指检查数据的准确性和一致性。
- not null:非空
- default:默认值
- unique key (UK):值唯一
- primary key (PK):主键(非空、唯一),可以是单字段,也可以是多字段
- auto_increment:自增,一个表中只能有一个字段用该约束,且必须是整数类型
- unique (FK):外键,构建两个表之间的参照关系。设置FK约束的字段必须依赖于已存在父表的主键,两者数据类型必须一致。外键可以为null
根据约束数据列限制,约束可分为:单列约束,即每个约束只约束一列数据;多列约束,即每个约束可以约束多列数据。
- 设置非空约束:
create table 表名(
属性名 数据类型 not null,
...
);
- 设置字段默认值:
create table 表名(
属性名 数据类型 default 默认值, # 如果是字符串需要加单引号或双引号
...
);
- 设置唯一约束:
create table 表名(
属性名 数据类型 uniqeu,
constraint uk_属性名 unique(属性名), # 其中“uk_属性名”是为uk约束设置的名字
...
);
- 设置主键约束:
单字段主键
create table 表名(
属性名 数据类型 primary key,
constraint pk_属性名 primary key(属性名), # 其中“pk_属性名”是为pk约束设置的名字
...
);
多字段主键
create table 表名(
属性名 数据类型,
...,
constraint pk_属性名 primary key(属性名1, 属性名2, ...) # 其中“pk_属性名”是为pk约束设置的名字
);
- 设置字段值自增:
create table 表名(
属性名 数据类型 auto_increment,
...
);
- 设置外键约束:
create table 表名(
属性名 数据类型 not null,
...,
constraint 外键约束名 unique(属性名1) # 属性名1是子表中设置外键的字段名
references 表名(属性名2) # 属性名2是父表中设置主键约束的字段名
);
四、索引的操作
索引是创建在数据库表对象上的,由表中的一个字段或多个字段生成的键组成,这些键存储在数据结构(B-树或哈希表)中,其目的是提高从表中检索数据的速度。索引可以分为B型树索引和哈希索引。
MySQL支持6种索引,分别是普通索引、唯一索引、全文索引、单列索引、多列索引、空间索引。
普通索引
即创建索引时,不附加任何限制条件(唯一、非空等),该类型的索引可以创建在任何数据类型的字段上。
- 创建表时创建普通索引:
create table 表名(
属性名 数据类型,
...,
index|key [索引名](属性名1 [(长度)] [ASC|DESC])
);
- 查看索引是否被使用:
explain select * from 表名 where 属性名=1;
- 在已存在表上创建普通索引:
create index 索引名
on 表名 (属性名 [(长度)] [ASC|DESC]);
或
alter table 表名
add index|key 索引名 (属性名 [(长度)] [ASC|DESC]);
唯一索引
即在创建索引时,限制索引的值必须唯一,可以更加快的查询某条记录
自动索引是指在表里设置完整性约束时,该表会被系统自动创建索引
- 创建表时创建唯一索引:
create table 表名(
属性名 数据类型,
...,
unique index|key [索引名](属性名1 [(长度)] [ASC|DESC])
);
- 在已存在表上创建唯一索引:
create unique index 索引名
on 表名 (属性名 [(长度)] [ASC|DESC]);
或
alter table 表名
add unique index|key 索引名 (属性名 [(长度)] [ASC|DESC]);
全文索引
全文索引主要关联在数据类型为char/varchar和text的字段上,以便能够更加快速的查询数据量比较大的字符串类型的字段
只能在存储引擎为MyISAM的数据库表上创建全文索引,默认情况下全文索引的搜索方式不区分大小写
- 创建表时创建全文索引:
create table 表名(
属性名 数据类型,
...,
fulltext index|key [索引名](属性名1 [(长度)] [ASC|DESC])
);
- 在已存在表上创建全文索引:
create fulltext index 索引名
on 表名 (属性名 [(长度)] [ASC|DESC]);
或
alter table 表名
add fulltext index|key 索引名 (属性名 [(长度)] [ASC|DESC]);
多列索引
即在创建索引时,所关联的字段不是一个字段,而是多个字段。虽然一通过所关联的字段进行查询,但只有查询条件中使用了所关联字段的第一个字段,多列索引才会被使用。
- 创建表时创建多列索引:
create table 表名(
属性名 数据类型,
...,
index|key [索引名](属性名1 [(长度)] [ASC|DESC],
...,
属性名n [(长度)] [ASC|DESC])
);
- 在已存在表上创建多列索引:
create index 索引名
on 表名 (属性名1 [(长度)] [ASC|DESC],
...,
属性名n [(长度)] [ASC|DESC]);
或
alter table 表名
add fulltext index|key 索引名 (属性名1 [(长度)] [ASC|DESC],
...,
属性名n [(长度)] [ASC|DESC]);
删除索引
drop index 索引名
on 表名;
五、视图的操作
为了提高复杂SQL语句的复用性和表操作的安全性,MySQL提供了视图特性。视图本质上是一种虚拟表。
视图的建立和删除不影响基本表,对视图内容的增删改直接影响基本表,当视图来自多个基本表时,不允许添加和删除数据。
- 创建视图:
create view 视图名 # 视图名不可与表名相同
as 查询语句; # 相当于把查询语句封装起来重新起了个名,以便复用
- 封装实现查询常量语句的视图,即常量视图:
create view 视图名
as
select 3.1415926;
- 封装使用聚合函数(sum/min/max/count等)查询语句的视图:
create view 视图名
as
select count(属性名)
from 表名;
- 封装了实现排序功能查询语句的视图:
create view 视图名
as
select 属性名1
from 表名
order by 属性名 desc;
- 封装了实现表内连接查询语句的视图:
create view 视图名
as
select t1.属性名
from 表名1 as t1, 表名2 as t2
where t1.属性名=t2.属性名 and t2.属性名=值;
- 封装了实现表外连接(left join和right join)查询语句的视图:
create view 视图名
as
select t1.属性名
from 表名1 as t1 left join 表名2 as t2 on t1.属性名=t2.属性名
where t2.属性名=值;
- 封装了实现子查询相关查询语句的视图:
create view 视图名
as
select t1.属性名
from 表名1 as t1
where t1.属性名 in (select 属性名 from 表名2);
- 封装了实现记录联合(union和union all)查询语句的视图:
create view 视图名
as
select 属性名 from 表名1
union all
select 属性名 from 表名2;
- 使用视图:
select * from 视图名;
- 查看所有表和视图:
use tables;
- 查看表和视图的详细信息:
show tables status from 数据库名;
- 查看视图定义:
show create view 视图名;
- 查看视图设计信息:
describe|desc 视图名;
- 删除视图:
drop view 视图名 [,视图名2,...];
- 修改视图:
create or replace view 视图名
as 查询语句;
或
alter 视图名
as 查询语句;
六、触发器
当执行表事件时会激活触发器,从而执行其包含的操作。可激活触发器的语句有delete/insert/update语句。
对于具有相同触发程序动作事件和事件的给定表,不能有两个触发器。
- 创建有一条执行语句的触发器:
create trigger 触发器名
before|after 触发事件 # 在触发器事件的前/后执行,触发事件包括delete/insert/update语句
on 表名 for each row trigger_STMI参数;
- 创建包含多条执行语句的触发器:
create trigger 触发器名
before|after 触发事件 # 在触发器事件的前/后执行,触发事件包括delete/insert/update语句
on 表名 for each row
begin
trigger_STMI参数; # 用分号将不同的执行语句分开
trigger_STMI参数;
end
- 查看触发器:
show triggers;
- 删除触发器:
drop trigger 触发器名;
七、数据的操作
- 插入完整数据记录:
insert into 表名(字段名1,字段名2,...) # 顺序任意,只要和值对应即可
values(值1,值2,...);
或
insert into 表名 # 为完整记录时,字段名可省略
values(值1,值2,...);
- 插入数据记录的一部分:
insert into 表名(字段名1,字段名2,...)
values(值1,值2,...);
- 插入多条完整数据记录:
insert into 表名
values(值11,值21,...),
...
values(值n1,值n2,...);
- 插入多条部分数据记录:
insert into 表名(字段名1,字段名2,...)
values(值11,值21,...),
...
values(值n1,值n2,...);
- 插入查询结果:将另一个表中的查询结果插入到表中,从而实现表数据值的复制功能
insert into 表名1(字段名11,字段名12,...) # 表1中的字段名
select (字段名21,字段名22,...) # 表2中的字段名
from 表名2
where 条件;
- 更新数据记录:
update 表名
set 字段名1=值1,
...,
字段名n=值n,
where 条件; # 如果条件让所有记录都满足,则更新全部;更新全部时也可直接去掉where条件
- 删除数据记录:
delete from 表名
where 条件;
八、单表数据记录查询
简单数据记录查询
- 查询指定字段数据:
select 字段名1,字段名2,...
from 表名;
- 查询所有字段数据:
select *
from 表名;
- 避免重复数据查询:
select distinct 字段名1,字段名2,...
from 表名;
- 实现数学四则运算(+、-、*、/、%)数据查询:
select 字段1,字段2 * 10 [别名|as 别名] # 字段2的值*10后的结果,“别名”是字段名2*10后的别名,可选
from 表名;
- 设置显示格式数据查询:
select concat(字段名1,"字符串:",字段名2 * 10) [别名] # 将三者当作字符串连接,并将结果设为“别名”
from 表名;
条件数据记录查询
- 带关系运算符和逻辑运算符的条件数据查询:
select *
from 表名
where 字段名1=值1 && 字段名2>值2;
- 带between and关键字的条件数据查询:
select *
from 表名
where 字段名 not between 值1 and 值2; #查询字段值不处于值1和值2之间的记录
- 带is null关键字的条件数据查询:
select *
from 表名
where 字段名 is null; # 空值记录的查询
- 带in关键字的条件数据查询:如果查询的集合中存在null,则不会对结果产生影响;如果使用not in,切查询的集合中存在null,则不会有任何查询结果。
select *
from 表名
where 字段名 in (值1,值2,...); # 查询字段值在该集合中的记录
- 带like关键字的条件数据查询:
select *
from 表名
where 字段名 like 值; # 模糊查询
# where name like "_A%"; # 查询name的第二个字符是A的数据
# where name like "%%"; # "%%"表示匹配所有
通配符_
可以匹配单个字符,%
可以匹配任意长度的字符。
MySQL支持的比较运算符:<, >, =, != (<>), >=, <=
MySQL支持的逻辑运算符:and (&&), or (||), xor, not (!)
- 排序数据记录查询:
select *
from 表名
where 条件
order by 字段名1 [asc|desc] [, 字段名2 [asc|desc]]; # 多字段排序时,先按第一字段排,若第一字段相同,则按第二字段排
- 限制数据记录查询数量:
select *
from 表名
where 条件
limit 起始偏移量, 显示的行数; # 起始偏移量默认为0,可不写
- 排序后显示其中部分数据记录:
select *
from 表名
where 条件
order by 字段名 limit 起始偏移量, 显示行数;
- 统计函数和分组数据记录查询:
- count():记录的条数。当为count(*)时,为null的也是一条记录,而为count(字段)时,为null的忽略掉。
- avg():字段值的平均值
- sum():字段值的总和
- max():字段值的最大值
- min():字段值的最小值
统计函数数据记录查询:
select 统计函数(字段名)
from 表名
where 条件;
简单分组数据记录查询:当数据值有重复时才可以进行分组
select *
from 表名
where 条件
group by 字段名; # group by单独使用时,默认查询出每个分组中随机的一条记录,具有很大的不确定性
实现统计功能分组查询:
select group_concat(字段名) # 显示每个分组中指定的字段值,即每组中某字段有哪些值
from 表名
where 条件
group by 字段名;
实现多个字段分组查询:
select *
from 表名
where 条件
group by 字段名1, 字段名2, ...; # 首先按照字段1分组,然后对每组按照字段2进行分组……
实现having子句限定分组查询:
select *
from 表名
where 条件
group by 字段名
having 条件; # 使用having对分组进行条件限制(如平均工资>1w),而不能用where
九、多表数据记录查询
连接查询分为内连接查询和外连接查询,在连接查询中首先需要对两张或两张以上的表进行连接操作。
关系数据操作
- 并(union):把具有相同子弹数目和字段类型的表合并在一起。如合并两张结构相同内容不用的学生表
- 笛卡尔积(Cartesian product):没有连接条件表关系返回的结果。结果表的字段是两张表字段的相加,结果表的记录数是表1的记录数表2的记录数。
连接可以分为内连接、外连接、交叉连接。
- 内连接(inner join):在表关系的笛卡尔积数据记录中,保留表关系中所有匹配的数据记录,舍弃不匹配的数据记录。按照匹配条件可以分为自然连接、等值连接、不等连接。
select *
from 左表名 inner join 右表名 [inner join 其他表名]
on 匹配条件; # 若匹配条件为相等关系,则为等值连接,如e.deptno=d.deptno;若不为相等关系(如>/>=/</<=/!=),则为不等连接
- 自然连接:在表关系的笛卡尔积中,首先根据表关系中相同名称的字段自动进行记录匹配,然后去掉重复的字段。结果表字段数为两张表字段的并(重复的字段只保留一次),结果表的记录数为表1的记录数表2的记录数 - 两表相同字段的值不相等的记录数。
- 等值连接:在表关系的笛卡尔积中,选择所匹配字段值相等的数据记录。结果表的字段数为表1的字段数+表2的字段数,结果表的记录数为表1的记录数表2的记录数 - 两表相同字段的值不相等的记录数。
# 自连接指表与表自身进行连接,是一种特殊的等值连接
select *
from 表名 inner join 表名
on 匹配条件;
- 不等连接:在表关系的笛卡尔积中,选择所匹配字段值不相等的数据记录。结果表的字段数为表1的字段数+表2的字段数,结果表的记录数为表1的记录数表2的记录数 - 两表相同字段的值相等的记录数。
- 外连接(outer join):在表关系的笛卡尔积数据记录中,不仅保留表关系中所有匹配的数据记录,还会保留部分不匹配的数据记录。
select *
from 左表名 left|right|full [outer] join 右表名
on 匹配条件;
- 左外连接:在表关系的笛卡尔积中,除了选择相匹配的数据记录,还包含关联左边表中不匹配的数据记录。结果表的字段数为表1的字段数+表2的字段数,结果表的记录数为左表的记录数右表的记录数 - 两表相同字段的值不相等的记录数+左表中未匹配的记录数。
- 右外连接:在表关系的笛卡尔积中,除了选择相匹配的数据记录,还包含关联右边表中不匹配的数据记录。结果表的字段数为表1的字段数+表2的字段数,结果表的记录数为左表的记录数右表的记录数 - 两表相同字段的值不相等的记录数+右表中未匹配的记录数。
- 全外连接:在表关系的笛卡尔积中,除了选择相匹配的数据记录,还包含关联左右边表中不匹配的数据记录。全外连接=左外连接右外连接。结果表的字段数为表1的字段数+表2的字段数,结果表的记录数为左表的记录数右表的记录数 - 两表相同字段的值不相等的记录数+左表中未匹配的记录数+右表中未匹配的记录数。
- 交叉连接:表关系笛卡尔积后数据记录。
- 合并查询数据记录:将多个select语句的查询结果合并在一起组成新的关系
select *
from
union | union all # union会去掉重复的数据记录,而union all则不会
select *
from
...
- 子查询:在一个select查询语句的where或from子句中包含另一个select语句。虽然可以通过连接查询实现多表查询数据记录,但因其性能很差,故不建议使用。
- where子句中的子查询:一般返回单行单列、多行单列、单行多列的数据记录
- from子句中的子查询:一般返回多行多列数据记录
关键字any:=any(子查询)功能与in相同,>any(子查询)是比子查询中返回数据记录中最小的还要大的数据记录,<any(子查询)是比子查询中返回数据记录中最大的还要小的数据记录
关键字all:>all(子查询)是比子查询中返回数据记录中最大的还要大的数据记录,<all(子查询)是比子查询中返回数据记录中最小的还要小的数据记录
关键字exists:exists(子查询)是一个布尔类型,当子查询返回结果集时为true,不能返回结果集时为false。
十、MySQL运算符
算术运算符
对于除法和取余操作,如果除数是0将是非法运算,返回结果为null。
-
+
:加 -
-
:减 -
*
:乘 -
/
:除 -
%
:取余
比较运算符
-
>
:大于 -
<
:小于 -
=
:等于 -
!=
:不等于,不可以对null进行判断 -
>=
:大于等于 -
<=
:小于等于 -
between and
:存在于指定范围 -
is null
:为空 -
in
:存在于指定集合 -
like
:通配符匹配 -
regexp
:正则表达式匹配
正则表达式
select * regexp '^c...g$'
,匹配以c开头,以g结尾,中间三个任意字符的字符串。
-
^
:匹配字符串开始的部分 -
$
:匹配字符串结束的部分 -
.
:匹配字符串中任意一个字符 -
[字符集合]
:匹配字符集合中任意一个字符 -
[^字符集合]
:匹配字符集合外任意一个字符 -
str1|str2|str3
:匹配三个字符串中任意一个字符串,中间不能有空格 -
*
:匹配字符,包含0个和1个 -
+
:匹配字符,包含1个 -
字符串{N}
:字符串出现N次 -
字符串(M,N)
:字符串至少出现M次,最多N次
逻辑运算符
-
and (&&)
:与 -
or (||)
:或 -
not (!)
:非 -
xor
:异或
位运算符
-
&
:按位与 -
|
:按位或 -
~
:按位取反 -
^
:按位异或 -
<<
:按位左移,补0 -
>>
:按位右移,补0
十一、MySQL常用函数
函数不仅可以出现在select语句及其子句中,而且还可以出现在update、delete语句中。
字符串函数
-
cancat(str1,str2,...)
:连接字符串 -
cancat_ws(sep,str1,str2,...)
:cancat with separator的缩写,在连接时通过分隔符sep将它们分割 -
insert(str,x,y,instr)
:在字符串str从第x位置开始,y个字符长的子串替换为instr -
lower(str)
:所有字符变为小写,功能同lcase(str)
-
upper(str)
:所有字符变为大写,功能同ucase(str)
-
left(str,x)
:字符串str最左边的x个字符 -
right(str,x)
:字符串str最右边的x个字符 -
lpad(str,n,pad)
:使用字符串pad对字符串str最左边进行填充,直到长度为n -
rpad(str,n,pad)
:使用字符串pad对字符串str最右边进行填充,直到长度为n -
ltrim(str)
:去掉字符串左边的空格 -
rtrim(str)
:去掉字符串右边的空格 -
repeat(str,x)
:字符串str重复x次 -
replace(str,a,b)
:使用字符串b替换字符串str中所有出现的字符串a -
strcmp(str1,str2)
:比较字符串str1和str2,若str1>str2则返回1,str1<str2则返回-1,相等返回0 -
trim(str)
:去掉字符串两端的空格 -
substring(str,x,y)
:字符串str中从x位置起,y个字符长度的字符串,作用同mid(str,x,y)
-
length(str)
:字符串长度,一个汉字占两个字节,故长度为2 -
char_length(str)
:字符串长度,一个汉字的长度为1 -
find_in_set(str1,str2)
:返回字符串str2中与str1相匹配的字符串的位置,参数str2字符串中将包含若干用逗号分割的字符串 -
field(str,str1,str2,...)
:返回第一个与字符串str匹配的字符串的位置 -
locate(str1,str)
:返回str中字符串str1的开始位置,作用同position(str1 in str)
、instr(str,str1)
-
elt(n,str1,str2,...)
:返回第n个字符串 -
make_set(num,str1,str2,...)
:首先将数字num转换为二进制,然后按照二进制从str1, str2, … 中选取相应的字符串
数值函数
-
abs(x)
:绝对值 -
cell(x)
:大于x的最大整数 -
floor(x)
:小于x的最大整数 -
mod(x,y)
:x模y的值 -
rand()
:返回0~1内的随机数,若为rand(x)
,在x一定时返回的随机数相同 -
round(x,y)
:返回数值x的四舍五入后有y位小数的数值,y默认为0,可不写 -
truncate(x,y)
:返回数值x截断为y为小数的数值
日期和时间函数
curdate()
:当前日期curtime()
:当前时间now()
:当前日期和时间unix_timestamp(date)
:获取日期date的unix时间戳from_unixtime()
:获取unix时间戳的日期week(date)
:日期date为一年中的第几周year(date)
:日期date的年份monthname(date)
:日期date的月份值hour(time)
:时间time的小时值minute(time)
:时间time的分钟值adddate(date,n)
:计算日期date加上n天后的日期subdate(date,n)
:计算日期date减去n天后的日期addtime(time,n)
:计算时间time加上n秒后的时间subtime(time,n)
:计算时间time减去n秒后的时间
系统信息函数
-
version()
:数据库版本号 -
database()
:当前数据库名 -
user()
:当前用户 -
last_insert_id()
:最近生成的auto_increment值
其他函数
-
if(value,t,f)
:如果value为真则返回t,反之返回f -
ifnull(value1,value2)
:如果value不为空则返回value1,反之返回value2
十二、存储过程和函数的操作
一个完整的操作会包含多条SQL语句,在执行过程中需要根据前面的SQL语句的执行结果有选择的执行后面的SQL语句。
创建存储过程和函数
存储过程和函数就是事先经过编译并存储在数据库中的一段SQL语句集合。函数必须有返回值,而存储过程没有。
- 创建存储过程
create procedure 存储过程名(存储过程参数[,...])
[存储过程特征] 存储过程的SQL语句 # 可以用begin...end来标志SQL语句的开始和结束
存储过程参数由输入/输出类型、参数名和参数类型组成,即[in|out|inout] 参数名 参数类型
,in表示输入类型,out表示输出类型,inout表示输入/输出类型
存储过程特征的取值为:
language SQL
|[not] deterministic
|{contains SQL|no SQL|reads SQL data|modifies SQL data}
|SQL security {definer|invoker}
|comment 字符串
- language SQL:表示存储过程的SQL语句由SQL语言的语句组成
- [not] deterministic:表示存储过程的执行结果是否是确定的
- {contains SQL|no SQL|reads SQL data|modifies SQL data}:表示使用SQL语句的限制,4个值分别表示可以包含SQL语句,但不包含读或写数据的语句、不包含SQL语句、包含读数据的语句、包含写数据的语句。默认值为contains SQL
- SQL security {definer|invoker}:设置谁有权限来执行,2个值分别表示只有定义者自己可以执行、调用者可以执行
- comment 字符串:注释语句
- 创建函数
create function 函数名([函数参数[,...]])
[函数特征] 函数的SQL语句
函数参数由参数名和参数类型两部分组成,即参数名 参数类型
。函数特征的取值与存储过程特征的取值相同。
存储过程和函数的表达式
表达式由变量、运算符和控制流程构成。
- 声明变量:可以通过变量存储从表中查询得到的数据等
declare 变量名[,...] 类型 [default 值] # 默认值为null
- 赋值变量:
set 变量名=赋值表达式[,...]
select 字段名[,...] into 变量名[,...] # 将查询结果赋值给变量时,返回结果只能是单行
from 表名
where 条件;
- 操作条件:条件的定义和处理可以用来定义在处理过程中遇到问题时相应的处理步骤
declare 条件名 condition for 条件值 # 条件值用来设置条件的类型
条件值可以是sqlstate[值] sql状态值|MySQL错误码
,用来设置条件的错误
- 定义处理程序:
declare 处理程序类型 handler for 条件值[,...] 程序语句段
处理程序类型可以是continue|exit|undo
,条件值可以是sqlstate[值] sql状态值|条件名|sql警告|not found|sql异常|MySQL错误码
- 游标:可以看作是一种数据类型,可以用来遍历结果集,相当于指针或数组中的下标
- 声明游标:
declare 游标名 cursor for select语句;
,若数据太多则不应使用游标 - 打开游标:
open 游标名
,打开一个游标时,游标指向第一条记录的前边 - 使用游标:
fetch 游标名 into 变量名[,...]
,变量必须在游标使用之前定义,当第一次使用游标时,游标指向第一条记录 - 关闭游标:
close 游标名
- 流程控制
- 条件控制语句
if 搜索条件 then 状态列表
[elseif 搜索条件 then 状态列表]...
[else 搜索条件]
end if
case case值
when when值 then 状态列表
[when when值 then 状态列表]...
[else 状态列表]
end case
- 循环控制语句
[开始标志:] loop
状态列表
end loop [结束标志]
# 使用leave label语句来跳出循环,其中label是循环的标志
[开始标志:] while 搜索条件 do # 满足条件时才执行
状态列表
end while [结束标志]
[开始标志:] repeat 搜索条件 do # 在满足条件时退出循环体
状态列表
end repeat [结束标志]
查看存储过程和函数
- 查看存储过程:
show procedure status [like 模式];
- 查看函数:
show function status [like 模式];
- 查看存储过程的定义信息:
show create procedure 存储过程名;
- 查看函数的定义信息:
show create function 函数名;
修改存储过程和函数
- 修改存储过程
alter procedure 存储过程名
[存储过程特征] # 指定修改后的存储过程的特征
存储过程特征取值有:
|{contains sql|no sql|reads sql data|modifies sql data}
| sql security {definer|invoker}
|commit 字符串
- 修改函数
alter function 函数名
[函数特征] # 其取值和存储过程特征相同
删除存储过程和函数
- 删除存储过程:
drop procedure 存储过程名;
- 删除函数:
drop function 函数名;
十三、MySQL事务
事务概述
事务具有以下4个特征:
- 原子性:对于事务所进行的数据修改等操作只能是完全提交或完全回滚
- 一致性:事务在完成时,必须使所有的数据从一种一致性状态变成另一种一致性状态
- 隔离性:一个事务中的操作语句所做的修改必须与其他事务所做的修改相隔离
- 持久性:事务完成后,所做的修改对数据的影响是永久的
为支持事务,InnoDB存储引擎引入了与事务处理相关的UNDO日志和REDO日志,REDO日志是事务执行时将执行的事务所写入的日志,UNDO日志只要用于事务异常时的数据回滚。
MySQL事务控制语句
MySQL中使用begin开始事务,使用commit结束事务,中间可以使用rollback回滚事务,通过以下语句支持本地事务:
start transaction|begin [work]
commit [work] [and [no] chain] [[no] release]
rollback [work] [and [no] chain] [[no] release]
set autocommit={0|1}
MySQL事务隔离级别
隔离级别指事务中哪些数据改变其他事务可见,哪些数据改变其他事务不可见,低级别的隔离级别可以支持更高的并发处理,同时占用的系统资源相对较少。
- 设置隔离级别
# 未提交读
set global transaction isolation level read uncommitted;
# 提交读
set global transaction isolation level read committed;
# 可重复读
set global transaction isolation level repeatable read;
# 可串行化
set global transaction isolation level serializable;
未提交读:所有的事务都可以看到其他未提交事务的执行结果,读取未提交的数据被称为脏读
提交读:一个事务从开始到提交前所做的任何改变都是不可见的,事务只能看见已经提交事务所做的改变。这种隔离级别也支持不可重复读
可重复读:MySQL的默认事务隔离级别,能确保同一事务的多个实例在并发读取数据时,会看到同样的数据行,这理论上会导致幻读。
可串行化:通过强制事务排序,使之不可能相互冲突,从而解决幻读问题,即在每个读的数据行上加上共享锁实现。
- 脏读:某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个回滚了操作,则后一个事务所读取的数据就会是不正确的。
- 不可重复读:在一个事务的两次查询之中数据不一致,这可能是有次查询过程中其他事务更新了原有的数据。
- 幻读:在一个事务的两次查询中数据的笔数不一致,例如有一个事务查询了几行数据,而另一个事务却在此时插入了新的几行数据,先前的事务在接下来的查询中,就会发现有几行数据是他先前所没有的。
InnoDB锁机制
- 共享锁:代号是S,即Share的缩写。共享锁的粒度是行或元组(多个行)。一个事务获取了共享锁之后,可以对锁定范围内的数据执行读操作。
- 排它锁:代号是X,即eXclusive的缩写。排它锁和共享锁的粒度相同。一个事务获取了排它锁之后,可以对锁定范围内的数据执行写操作。
- 意向锁:是一种表锁,粒度为整张表。分为意向共享锁(IS)和意向排他锁(IX)。意向表示事务想执行但还没有真正执行。
MySQL锁的兼容情况
参数 | X | S | IX | IS |
X | N | N | N | N |
S | N | Y | N | Y |
IX | N | N | Y | Y |
IS | N | Y | Y | Y |
锁的粒度朱啊哟分为表锁和行锁,表锁的开销最小,同时允许的并发量也是最小的。