MySQL基础

Posted by Beyonderwei on 2019-10-16
Words 9.6k and Reading Time 36 Minutes
Viewed Times

DBMS:

  1. DBMS:数据库管理系统

    实际上数据库还是通过一套软件来管理文件中的数据。

    • 基于共享文件系统的DBMS 如access
    • 基于客户机/服务器的DBMS: MySQL Oracle等

目标

注:画五角星的要随时都可以写出来。

一、为什么要学习数据库
二、数据库的相关概念      
    DBMS、DB、SQL
三、数据库存储数据的特点
四、初始MySQL
    MySQL的介绍        
    MySQL的安装          ★        
    MySQL服务的启动和停止     ★
    MySQL服务的登录和退出     ★      
    MySQL的常见命令和语法规范      
五、DQL语言的学习   ★              
    基础查询        ★             
    条件查询         ★            
    排序查询         ★                
    常见函数        ★               
    分组函数        ★              
    分组查询           ★            
    连接查询         ★            
    子查询       √                  
    分页查询       ★              
    union联合查询    √            

六、DML语言的学习    ★             
    插入语句                        
    修改语句                        
    删除语句                        
七、DDL语言的学习  
    库和表的管理     √                
    常见数据类型介绍  √          
    常见约束        √            
八、TCL语言的学习
    事务和事务处理                 
九、视图的讲解           √
十、变量                      
十一、存储过程和函数   
十二、流程控制结构       

一、数据库的好处

​ 1.持久化数据到本地
​ 2.可以实现结构化查询,方便管理

二、数据库相关概念

​ 1、DB:数据库,保存一组有组织的数据的容器
​ 2、DBMS:数据库管理系统,又称为数据库软件(产品),用于管理DB中的数据
​ 3、SQL:结构化查询语言,用于和DBMS通信的语言

数据库存储数据的特点:

​ 1、将数据放到表中,表再放到库中
​ 2、一个数据库中可以有多个表,每个表都有一个的名字,用来标识自己。表名具有唯一性。
​ 3、表具有一些特性,这些特性定义了数据在表中如何存储,类似java中 “类”的设计。
​ 4、表由列组成,我们也称为字段。所有表都是由一个或多个列组成的,每一列类似java 中的”属性”
​ 5、表中的数据是按行存储的,每一行类似于java中的“对象”。

三、MySQL的介绍和安装

配置文件位置

  1. 进入MySQL容器 :docker exec -it 容器ID /bin/bash
  2. /etc/mysql/my.cnf (需要安装vim打开 apt-get install -y vim

Docker中操作

进入容器后:

  1. 登录MySQL:mysql -u root -p
  2. exit 退出MySQL

MySQL的常见命令

1.查看当前所有的数据库
show databases;
2.打开指定的库
use 库名
3.查看当前库的所有表
show tables;
4.查看其它库的所有表
show tables from 库名;
5.创建表
create table 表名(

    列名 列类型,
    列名 列类型,
    。。。
);
6.查看表结构
desc 表名;


7.查看服务器的版本
方式一:登录到mysql服务端
select version();
方式二:没有登录到mysql服务端
mysql --version
或
mysql --V

MySQL的语法规范

​ 1.不区分大小写,但建议关键字大写,表名、列名小写
​ 2.每条命令最好用分号结尾
​ 3.每条命令根据需要,可以进行缩进 或换行
​ 4.注释
​ 单行注释:#注释文字
​ 单行注释:— 注释文字
​ 多行注释:/ 注释文字 /
​ 5.name 1旁白你的字符,表示着重符,当表中存在纯大写的字段时加上着重符,防止被认为是关键字


SQL的语言分类

​ DQL(Data Query Language):数据查询语言
​ select
​ DML(Data Manipulate Language):数据操作语言
​ insert 、update、delete
​ DDL(Data Define Languge):数据定义语言
​ create、drop、alter
​ TCL(Transaction Control Language):事务控制语言
​ commit、rollback

SQL的常见命令

show databases; 查看所有的数据库
use 库名; 打开指定 的库
show tables ; 显示库中的所有表
show tables from 库名;显示指定库中的所有表
create table 表名(
    字段名 字段类型,    
    字段名 字段类型
); 创建表

desc 表名; 查看指定表的结构
select * from 表名;显示表中的所有数据

四、DQL语言的学习

Data Query Language

进阶1:基础查询

​ 语法:
​ SELECT 要查询的东西
​ 【FROM 表名】;

类似于Java中 :System.out.println(要打印的东西);
特点:
①通过select查询完的结果 ,是一个虚拟的表格,不是真实存在
② 要查询的东西 可以是常量值、可以是表达式、可以是字段、可以是函数
  1. select 常量值; 并不是去库中查询,是支持这样的运算
  2. select 表达式; 可以在要查询的东西中加入表达式
  3. select 函数; 调用该函数,并得到函数的返回值
  4. select name AS 名字 from account; 给查询的字段取一个别名。(为了在查询的字段中有重名时区分开来)住:AS可以不写 用空格代替,当别名中包含关键字时用双引号括起来。
  5. select DISTINCT class_number from class; 在要查询的字段前加上 DISTINCT 去除重复的班级号
  6. “+” 只是运算符,不会拼接字符串,
    • select ‘abc’+123 不能转换成数值的字符串都会被认为是0。
    • select ‘123’+456 结果为579
    • select null+123 有null则结果永远为null
    • :如果要将两个字段拼在一起查询用CONCAT函数,参考函数章节。

进阶2:条件查询

条件查询:根据条件过滤原始表的数据,查询到想要的数据
语法:
select 
    要查询的字段|表达式|常量值|函数
from 
    表
where 
    条件 ;

分类:
一、条件表达式
    示例:salary>10000
    条件运算符:
    > < >= <= = <> != 

二、逻辑表达式
示例:salary>10000 && salary<20000

逻辑运算符:

    and(&&):两个条件如果同时成立,结果为true,否则为false
    or(||):两个条件只要有一个成立,结果为true,否则为false
    not(!):如果条件成立,则not后为false,否则为true

三、模糊查询 
    运算符:like、between and、in、is null、is not null
    示例:last_name like 'a%' 

①.LIKE

  1. select from account where name LIKE ‘%a%’ ; 表示名字中带有字母a的(注:通配符% ,表示任意多个字符,*不区分大小写
  2. select from account where name LIKE ‘_a%’ ; 表示第二个字符为a的名字(*通配符下划线 表示任意单个字符)
  3. 转义字符,比如查询带有下划线时,同样是通过“\”来转义
  4. 自定义转义字符:select * from account where name LIKE ‘^_%’ ESCAPE ‘^’; 自定义”^” 为转义字符

②. BETWEEN AND

  1. select from account where number BETWEEN 10 AND 20; 员工编号在10到 20之间。(使语法简洁,*包含临界值
  2. 规则:大于等于左边,小于的等于右边的值,不能颠倒

③. IN

  1. select * from account where type IN (‘assistant’, ‘teacher’); 查询用户类型为助教和老师的用户(避免写过多的或判断条件)
  2. 规则:IN 后()中的内容类型应该相同,且括号中的内容不支持通配符。

④. is NULL

  1. select * from account where tel IS NOT NULL; 查询用户的tel信息为空(非空)的用户。
  2. 规则:= 和 <> 无法判断该栏是否为空,同样is也不能判断是否等于一个值。

进阶3:排序查询

语法:
select
    要查询的东西
from
    表
where 
    条件

order by 排序的字段|表达式|函数|别名 【asc|desc】

descend:降序  ascend:升序(可省略,加上order by 默认升序)
  1. select salary*12 年薪 FROM employee ORDER BY 年薪 DESC; 可按照表达式排序
  2. select salary FROM employee ORDER BY salary ASC,num DESC; 先按照员工的工资升序排列,工资一样的按工号降序排列。

进阶4:常见函数

  1. 调用函数:select 函数名(实参列表) [from 表名];
  2. 函数可以嵌套调用,某个函数的返回值可以作为另一个函数的参数。
  3. MySQL中的索引都是从1开始的。
  4. 只有 LENGTH中是按照字节算,其余都按照字符算。

一、单行函数

1、字符函数
    concat拼接
        select CONCAT(lastname,firstname) 姓名 from 表名
    substr截取子串
        select SUBSTR(name,1,5)  从1开始截取截取3个长度字符长度(不是字节长度)。
    upper转换成大写
    lower转换成小写
    trim去前后指定的空格和字符
        默认去空格,去特殊字符需指定。
        select TRIM('_' FROM name)  去掉name字段前后的下划线。
    ltrim去左边空格
    rtrim去右边空格
    replace替换
    lpad左填充
    rpad右填充
    instr返回子串第一次出现的索引
    length 获取字节个数

2、数学函数
    round 四舍五入
        select ROUND(1.456,2)  小数点后保留两位四舍五入
    rand 随机数
        返回大于等于该数的最小整数
    floor向下取整
        返回小于等于该数的最小整数
    ceil向上取整
    mod取余
        MOD(a,b) 结果返回的为   a-a/b*b
    truncate截断
3、日期函数
    now当前系统日期+时间
        SELECT YEAR(NOW()) 年   只获取日期中的年 还包括MONTH()、MONTHNAME()
    curdate当前系统日期
    curtime当前系统时间
    str_to_date 将字符转换成日期
    date_format将日期转换成字符
4、流程控制函数
    if 处理双分支
    case语句 处理多分支
        情况1:处理等值判断
        情况2:处理条件判断

5、其他函数
    select version();    版本
    select database();    当前库
    select user();    当前连接用户
  1. 日期格式化输出 str_to_date

    select DATA_FORMAT(NOW(),’%y年%月%日’);

序号 格式符 功能
1 %Y 四位年份
2 %y 2位月份
3 %m 月份(01,02…11,12)
4 %c 月份(1,2…11,12)
5 %d 时(01,02…)
6 %H 小时(24小时制)
7 %h 小时(12小时制)
8 %i 分钟(01,02,…59)
9 %s 秒(00,01,…59)
  1. 流程控制函数

    select IF(age>35,’开除’, ‘不开除’) 状态 FROM account; 相当于三元运算符

二、分组函数(又叫统计函数聚合函数

    sum 求和(NULL不参与运算)
    max 最大值(NULL不参与运算)
    min 最小值(NULL不参与运算)
    avg 平均值(NULL不参与运算)
    count 计数(NULL不参与运算)

    特点:
    1、以上五个分组函数都忽略null值,除了count(*)
    2、sum和avg一般用于处理数值型
        max、min、count可以处理任何数据类型
    3、都可以搭配distinct使用,用于统计去重后的结果
    4、count的参数可以支持:
        字段、*、常量值,一般放1

       建议使用 count(*)  可查看有多少行(只要任意一个字段不为nUll就会被统计)
  1. select OCUNT(DISTINCT person_type) 对类型去重后计数,其他函数也可以这样用,可以被 IN 等代替,因此用的较少。这里,子查询后执行,子查询在主查询结果中筛选,因此也叫相关子查询。
  2. 和分组函数一起查询的字段要是GROUP BY 后的字段,其他不可以。不然会出现只查出一个的情况。

进阶5:分组查询

语法:
select 分组函数,查询的字段(要求出现在分组函数的后面)
from 表
where [筛选条件]
group by 分组的字段[或者按函数结果分组]
HAVING [筛选条件]    # 指上面分组后再筛选,支持别名判断

​ 特点:
​ 1、可以按单个字段分组
​ 2、和分组函数一同查询的字段最好是分组后的字段
​ 3、分组筛选
​ 针对的表 位置 关键字
​ 分组前筛选: 原始表 group by的前面 where
​ 分组后筛选: 分组后的结果集 group by的后面 having

​ 4、可以按多个字段分组,字段之间用逗号隔开
​ 5、可以支持排序
​ 6、having后可以支持别名

​ select COUNT(*), name FROM account GROUP BY LENGTH(name) 按照函数的结果分组

进阶6:多表连接查询

笛卡尔乘积:如果连接条件省略或无效则会出现
解决办法:添加上连接条件

select boy_name, girl_name from boys, girls WHERE girls.boyfrend_id = boys.id; 查询每个男生的女朋友(当有多个查询条件是中间用AND连接)

一、传统模式下的连接 :等值连接——非等值连接

1.等值连接的结果 = 多个表的交集
2.n表连接,至少需要n-1个连接条件
3.多个表不分主次,没有顺序要求
4.一般为表起别名,提高阅读性和性能

二、sql99语法:通过join关键字实现连接

含义:1999年推出的sql语法
支持:
等值连接、非等值连接 (内连接)
外连接
交叉连接

语法:

select 字段,...
from 表1
【inner|left outer|right outer|cross】join 表2 on  连接条件
【inner|left outer|right outer|cross】join 表3 on  连接条件
【where 筛选条件】
【group by 分组字段】
【having 分组后的筛选条件】
【order by 排序的字段或表达式】

好处:语句上,连接条件和筛选条件实现了分离,简洁明了!

外连接:一个表中有,一个表中没有的查询

如果从表中有匹配的值,则显示匹配的值,从表中没有则显示NULL

外连接结果=内连接结果 + 主表有而从表没有的记录

  • 主表:left join左边,right join 右边,的是主表
  • 从表:

连接类型:左外->left 右外->right 全外->full 三、自连接

使用场景:查询员工名和直接上级的名称,当表中有该员工的领导id,但领导同时也是员工,也在这张表中的情况下使用。

sql99 (提高了可读性)

SELECT e.last_name,m.last_name
FROM employees e
JOIN employees m ON e.`manager_id`=m.`employee_id`;

sql92

SELECT e.last_name,m.last_name
FROM employees e,employees m 
WHERE e.`manager_id`=m.`employee_id`;

进阶7:子查询

子查询出现的位置: (加黑为重要)

select后 :仅支持标量子查询(结果集为一行一列)

from后 :支持表子查询(查询结果为多行多列)

where或having后 :支持标量子查询列子查询(查询结果为一列多行)、行子查询(查询结果为一行多列)

exists后:支持表子查询

含义:

​ 一条查询语句中又嵌套了另一条完整的select语句,其中被嵌套的select语句,称为子查询或内查询
在外面的查询语句,称为主查询或外查询

特点:

1、子查询都放在小括号内(结尾不要带分号
2、子查询可以放在from后面、select后面、where后面、having后面,但一般放在条件的右侧
3、子查询优先于主查询执行,主查询使用了子查询的执行结果
4、子查询根据查询结果的行数不同分为以下两类:
① 单行子查询
结果集只有一行,一般搭配单行操作符使用:> < = <> >= <=
非法使用子查询的情况:
a、子查询的结果为一组值
b、子查询的结果为空

② 多行子查询
结果集有多行
一般搭配多行操作符使用:any、all、in、not in
in: 属于子查询结果中的任意一个就行
any和all往往可以用其他查询代替

exists: 只关心查询结果有还是没有,有的话返回为1,没有返回为0。

例如: select EXISTS(select id from account where id=1000) r如果exist中的子查询语句结果存在,则返回1,否则返回0。

进阶8:分页查询(重要、常用)

应用场景:

实际的web项目中需要根据用户的需求提交对应的分页查询的sql语句

语法:

select 字段|表达式,...
from 表
【where 条件】
【group by 分组字段】
【having 条件】
【order by 排序的字段】
limit 【offset,】size;

offset:起始索引。
size:要显示的条目数。

特点:

  1. 起始条目索引从0开始

  2. limit子句放在查询语句的最后

  3. 公式:select from 表 limit (page-1)sizePerPage,sizePerPage
    假如:
    每页显示条目数sizePerPage
    要显示的页数 page

进阶9:联合查询

引入:
union 联合、合并,将多个查询的结果联合成一个结果

常用在在多个表中查询,多个表没有连接关系,但查询的信息一样,最后合并成一个结果

select * from china where sex=’男’

union

select* from american where sex=’male’

语法:

select 字段|常量|表达式|函数 【from 表】 【where 条件】
union 
select 字段|常量|表达式|函数 【from 表】 【where 条件】 
union 
.....
select 字段|常量|表达式|函数 【from 表】 【where 条件】

特点:

1、多条查询语句的查询的列数必须是一致的
2、多条查询语句的查询的列的类型几乎相同,顺序一致。
3、union代表去重,union all代表不去重

DML语言

Data Manipulate Language

插入

语法一:(支持插入多行和子查询插入)
insert into 表名 (字段名,…) values(值1,…);

​ 插入多行的情况:insert into 表名(字段名,…) values(值1,…), values(值1,…), values(值1,…);

子查询插入: 将查询的结果集插入。

例如: insert into 表名 (id, name)

​ select id, name from 表名;

语法二:

​ insert into 表名

​ set 字段名=值, 字段名=值, 字段名=值,…;

特点:

1、字段类型和值类型一致或兼容,而且一一对应
2、可以为空的字段,可以不用插入值,或用null填充
3、不可以为空的字段,必须插入值
4、字段个数和值的个数必须一致
5、字段可以省略,但默认所有字段,并且顺序和表中的存储顺序一致

6、列的顺序可以颠倒,但是插入的值要与之一一对应。

修改

修改单表语法:

update 表名 set 字段=新值,字段=新值
【where 条件】

修改多表语法:

update 表1 别名1,表2 别名2
set 字段=新值,字段=新值
where 连接条件
and 筛选条件

删除

方式1:delete语句

单表的删除: ★
delete from 表名 【where 筛选条件】

多表的删除:
delete 别名1,别名2 # 这里可以写一个表,这样只删除一个表的数据
from 表1 别名1,表2 别名2
where 连接条件
and 筛选条件;

方式2:truncate语句

truncate table 表名

两种方式的区别【面试题

  1. truncate不能加where条件,而delete可以加where条件

  2. truncate的效率高一丢丢

  3. truncate 删除带自增长的列的表后,如果再插入数据,数据从1开始delete 删除带自增长列的表后,如果再插入数据,数据从上一次的断点处开始

  4. truncate删除不能回滚,delete删除可以回滚

五、DDL语句

Data Define Language

库和表的管理

库的管理:

库名是不支持修改的。

一、创建库
create database 库名
CREATE database IF NOT EXISTS 库名    有的话就不会再创建了
二、删除库
drop database 库名
DROP DATABASE IF EXISTS 库名;    如果存在才删除
三、修改库的字符集
alter database 库名 CHARACTER SET utf8;   默认为utf8

表的管理:
1.创建表

CREATE TABLE IF NOT EXISTS stuinfo(
    stuId INT,
    stuName VARCHAR(20),
    gender CHAR,
    bornDate DATETIME

​ );

​ DESC studentinfo; 查看表结构

​ 2.修改表 alter
​ 语法:ALTER TABLE 表名 ADD|MODIFY|DROP|CHANGE COLUMN 字段名 【字段类型】;

​ ①修改字段名

​ ALTER TABLE studentinfo CHANGE COLUMN sex gender CHAR;

​ ②修改表名

​ ALTER TABLE stuinfo RENAME [TO] studentinfo;

​ ③修改字段类型和列级约束

​ ALTER TABLE studentinfo MODIFY COLUMN borndate DATE ;

​ ④添加字段

​ ALTER TABLE studentinfo ADD COLUMN email VARCHAR(20) first;

​ ⑤删除字段

​ ALTER TABLE studentinfo DROP COLUMN email;
​ #3.删除表
​ DROP TABLE [IF EXISTS] studentinfo;

复制表:

  1. 复制表的结构(数据不复制,仅复制表的结构)

    CREATE TABLE 表名(要得到的表) LIKE 表名(被复制的表)

  2. 复制部分结构,加部分数据

    CREATE TABLE 表名(要得到的表)

    SELECT 字段1,字段2 FROM 表名(被复制的表)

    WHERE 筛选条件;

  3. 仅复制表的部分结构(只需将筛选条件设为假)

    CREATE TABLE 表名(要得到的表)

    SELECT 字段1,字段2 FROM 表名(被复制的表)

    WHERE 0;

常见类型

  1. 数值型:

    • 整数型 :tinyint 、smallint 、mediumint、 int/integer、bigint

      整数形括号内的数值表示长度,对数值范围没有影响,仅仅影响在数据库表中显示的长度,不够长度用0填充。

    • 小数型:

      浮点型:float(M,D)、double(M,D)
        定点型:dec(M,D)保存精度更高时用。
      

      ​ M: 总共的位数(等于小数点前的位数加上小数点后的位数)。

      ​ D: 小数点后的位数(多的四舍五入,少的补零)

  2. 字符型:

    | | 写法 | M | 特点 | 空间 | 效率 |
    | ———- | ————— | ——————————- | —————————————- | —— | —— |
    | char | char(M) | 最大字符数(0-255) | 固定长度(M多大分配多大) | 耗费 | 高 |
    | varchar | varchar(M) | 最大字符数(0-65535) | 可变长度(小于M时按需分配) | 节省 | 低 |

    注意:char中M可以省略,默认为1,varchar中不能省略。

    如何选择:当固定字符数时用char,字符数不固定时用varchar。

    | | | | | | |
    | —— | ————————- | —— | —— | —— | —— |
    | enum | enum(‘a’,’b’,’c’) | | | | |
    | | | | | | |

    ENUM : 枚举类型,要求插入的值只能为列表中指定的值之一(每次插入一个值)。

    ​ eg:create table tab_enum ( e1 ENUM(‘a’,’b’,’c’) );

    ​ insert into tab_enum (e1) values(‘a’);

    使用场景:适合于存储性别等这种有固定个数且只能唯一选择一个的。

    SET: 不同于枚举的是,允许插入多个。

    ​ eg:create table tab_set ( s1 ENUM(‘a’,’b’,’c’) );

    ​ insert into tab_set (s1) values(‘a,b’);

    注: ENUM 和SET 均不区分大小写。

  3. 日期型:

    | 日期类型 | 内容 |
    | ————- | ————— |
    | date | 日期 |
    | time | 时间 |
    | year | 年 |
    | datetime | 日期和时间 |
    | timestamp | 日期和时间 |

    注:datetime范围大,不受时区影响,timestamp受时区影响。

    • 设置时区:set time_zone=+10:00 设置为东十区
    • 查看当前时区:show variables like 'time_zone'
  4. Blob类型:

注意事项:
  1. 整型如果不设置,默认类型为有符号,

    无符号需要在类型后加unsigned 如:create table tab (num INT UNSIGNED);

  2. 插入数据超出范围,会默认取临界值。

  3. 整数插入的数据的范围是由类型决定的,括号内的数值仅仅在位数不够该数值位,且设置了ZEROFILL时有用(很少用)。

  4. 不显示声明浮点中的M和D时,浮点型数据在范围内就可,而定点型默认为MD为10和 0。

常见约束

约束:用于限制表中的数据,为了保证我们插入的数据的一致性。

SHOW INDEX FROM 表名 可以查看当前表所添加的约束。

  1. NOT NULL:非空(NN)
  2. DEFAULT:有默认值的字段
  3. UNIQUE:唯一(UQ)
  4. CHECK:检查约束,MySQL中不支持,但语法不报错。
  5. PRIMARY KEY:主键,非空、唯一(PK)
  6. FOREIGN KEY:外键,用来限制两个表之间的关系,保证该字段的值必须是关联表中与之关联的列的值。

注:

  • AI:自增(auto increment)
  • UN:无符号的(unsigned)
  • B : 二进制(binary)
  • ZF:零填充(zero fill)

添加约束: 在创建或修改表时添加约束。添加位置如下:

CREATE TABLE 表名 (

​ 字段名 类型 列级约束(如果多个列级约束则用空格分开),

​ 字段名 类型 列级约束,

​ 表级约束

表级约束内容:

约束类型(字段名)如:FOREIGN KEY(字段名) REFERENCES 表名(字段名)

约束分类(重要):

  • 列级约束:不支持在该位置添加外键约束
  • 表级约束:不支持在该位置添加非空和默认值的约束。

修改时添加或删除约束

  • alter table 表名 MODIFY COLUMN 字段名 VARCHAR(10) NOT NULL; 列级约束写法
  • alter table 表名 ADD DEFAULT(字段) 20; 表级约束写法
  • 添加外键:ALTER ATBLE 表1 ADD FOREING KEY(字段1) REFERENCES 表2(字段2)
  • 注: 删除约束时与添加数据时类似如:
    • alter table 表名 MODIFY COLUMN 字段名 VARCHAR(10) NULL; 列级约束写法

约束备注(面试)

  1. 主键和唯一键都支持组合键(不推荐这样设置),如将多个字段组合设置为主键或者唯一键,这样即这多个字段不同时一样,就是合法的。如名字和身份证号组合为主键,但两个人的名字可能相同,也合法。
  2. 语法: PRIMARY KEY(id,name)
  3. 外键:该表的外键必须是另一个表中的主键(常用)或者唯一键。插入数据时先插入到主表,再插入到从表,删除数据时,先删从表,再删主表。

TCL(Transaction Control Language)

DCL (Data Control Langusge)

六、数据库事务

数据库引擎: 因为MySQL的存储引擎有很多,常用的是innodb,myisam,memory等,而这三个中只有innodb是支持事务的。

  • show engines 查看当前数据库使用的引擎

含义

​ 通过一组逻辑操作单元(一组DML——sql语句),将数据从一种状态切换到另外一种状态

特点

如果其中某条SQL语句执行失败,则会进行回滚 ,即将之前执行的撤销,回到最开始的状态,所有语句都执行成功时,则事务被顺利执行。

事务的特点:(ACID)
原子性(Atomicity):要么都执行,要么都回滚
一致性(Consistency):保证数据的状态操作前和操作后保持一致
隔离性(Isolation):多个事务同时操作相同数据库的同一个数据时,一个事务的执行不受另外一个事务的干扰
持久性(Durablity):一个事务一旦提交,则数据将持久化到本地,除非其他事务对其进行修改

相关步骤:

1、开启事务
2、编写事务的一组逻辑操作单元(多条sql语句)
3、提交事务或回滚事务

事务的分类:

隐式事务,没有明显的开启和结束事务的标志

比如
insert、update、delete语句本身就是一个事务

显式事务,具有明显的开启和结束事务的标志

  1. 开启事务
    取消自动提交事务的功能

    • 查看自动提交是否开启:show variables like 'autocommit';
    • 取消自动提交:set autocommit=0;
  2. 编写事务的一组逻辑操作单元(多条sql语句)
    insert
    update
    delete

  3. 提交事务或回滚事务

例子:

1
2
3
4
set autocommit=0;
start transaction; # 写不写这一句都可以
# 一堆SQL 语句
commit;

问题: 事务执行完以后(commit后),autocommit是否会再次变为打开的状态。(不会),但是一般不需要重新打开,因为关闭的自动提交只针对该连接有效,通常不会在一个程序代码中进行多次事务操作。

使用到的关键字

set autocommit=0;
start transaction;

commit;
rollback; # 如果执行了回滚,则数据不会改变,即没有写到磁盘。

savepoint  断点
commit to 断点
rollback to 断点

事务的隔离级别:

事务并发问题如何发生?

当多个事务同时操作同一个数据库的相同数据时

事务的并发问题有哪些?

脏读:一个事务读取到了另外一个事务未提交的数据
不可重复读:同一个事务中,多次读取到的数据不一致
幻读:一个事务读取数据时,另外一个事务进行更新,导致第一个事务读取到了没有更新的数据

如何避免事务的并发问题?

隔离级别越高,则效率就越低。

事务的隔离级别
1、READ UNCOMMITTED  脏读、不可重复读和幻读均可能出现
2、READ COMMITTED 可以避免脏读
3、REPEATABLE READ 可以避免脏读、不可重复读和一部分幻读
4、SERIALIZABLE可以避免脏读、不可重复读和幻读

设置隔离级别:

注意: 每启动一个MySQL连接,该连接就会有一个全局变量@@tx_isolation 表示当前的隔离级别。

  1. 设置数据库系统全局的隔离级别(重启后才有效)

    1
    set global  transaction isolation level 隔离级别名;
  2. 设置当前连接的隔离级别

    1
    set session transaction isolation level 隔离级别名;

注: 连接数据库的软件相当于开了一个连接。

查看隔离级别:

select @@tx_isolation;

补充

  1. 在事务中删除表时,delete 支持回滚,而truncate不支持回滚。

  2. 例如:TRUNCATE 后不支持回滚,数据还是会被删除。

    • SET autocommit=0;

      START TRANSACTION;

      TRUNCATE TABLE 表名;

      ROLLBACK;

七、视图

疑问: 如果在创建视图后表有更新,那么下一次调用视图的查询是否会也跟着更新?

含义:理解成一张虚拟的表(MySQL 5.1之后版本的新特性),行和列的数据来自定义视图的查询中所生成的表,在使用视图时动态生成,只保存了SQL逻辑,不保存查询内容。

使用场景:

​ 多个地方用到同样的查询结果,该查询结果使用的SQL语句较复杂时。

视图和表的区别:

由于视图和表基本完全相同,因此像表与视图连接的查询也是支持的。

    使用方式    占用物理空间

视图    完全相同    不占用,仅仅保存的是sql逻辑(一般不进行增删改)

表    完全相同    占用

视图的好处:

  1. sql语句提高重用性,效率高

  2. 和表实现了分离,提高了安全性

    安全性: 可针对不同的用户设定不同的视图,比如我表中包含了很多其他的数据,有隐私型数据,但是我通过视图返回数据,这样就提高了安全性,视图中只包含了该用户想知道的数据。

  3. 对数据库重构,不影响程序的运行。

视图的创建

​ 语法:
​ CREATE VIEW 视图名
​ AS
​ 查询语句;

视图的数据的增删改查(不建议这么做)

重要: 在视图中更删改数据后,那么原始的表也会跟着改变。

一般不对视图的数据进行增删改查,对视图设置权限,只允许读。

1、查看视图的数据 ★

SELECT * FROM my_v4;
SELECT * FROM my_v1 WHERE last_name='Partners';

2、插入视图的数据
INSERT INTO my_v4(last_name,department_id) VALUES('虚竹',90);

3、修改视图的数据

UPDATE my_v4 SET last_name ='梦姑' WHERE last_name='虚竹';

4、删除视图的数据
DELETE FROM my_v4;

某些视图不能更新

​ 包含以下关键字的sql语句:分组函数、distinct、group by、having、union或者union all
​ 常量视图
​ Select中包含子查询
​ join
​ from一个不能更新的视图
​ where子句的子查询引用了from子句中的表

视图SQL逻辑的更新

​ 1. 方式一:CREATE OR REPLACE VIEW 视图名 AS 查询语句
​ CREATE OR REPLACE VIEW test_v7
​ AS
​ SELECT last_name FROM employees
​ WHERE employee_id>100;

2. 方式二:ALTER VIEW 视图名 AS ;查询语句;
ALTER VIEW test_v7
AS
SELECT employee_id FROM employees;

SELECT * FROM test_v7;

视图的删除

​ DROP VIEW test_v1,test_v2,test_v3;

视图结构的查看

​ DESC test_v7;
​ SHOW CREATE VIEW test_v7;

八、变量

  1. 系统变量:
    • 全局变量:由系统提供,针对整个MySQL服务器的变量,每次启动后赋予默认初值,更改后跨链接有效,跨重启无效。
    • 会话变量:针对当前连接
  2. 自定义变量:
    • 用户变量:针对该用户
    • 局部变量:仅仅定义在begin end中有效(begin end中开始位置)

语法

系统变量:

默认为会话(session)级别,即session可以省略。

  1. show global|[session] variables; 查看所有的系统变量
  2. select @@global|[session].系统变量名; 查看指定变量的值
  3. set global|[session] 系统变量名=值; 为某变量赋值

自定义变量:

  1. SET @用户变量名:=值; 声明并初始化用户变量,或对某用户变量赋予新的值。
  2. SELECT 字段 INTO 用户变量名 FROM 表; 将查询结果付给变量。要求查询结果为一个,而不是多个。
  3. SELECT @用户变量名; 查看用户变量
  4. DECLARE 局部变量名 类型 [DEFAULT 值]; 声明局部变量(并赋初值。)
  5. SET @局部变量名 :=值; 为局部变量赋值
  6. SELECT 局部变量名; 查看局部变量的值

存储过程

含义:一组经过预先编译的sql语句的集合
好处:

1、提高了sql语句的重用性,减少了开发程序员的压力
2、提高了效率(减少了SQL语句的编译次数和跟数据库服务器连接的次数)
3、减少了传输次数

分类:

1、无返回无参
2、仅仅带in类型,无返回有参
3、仅仅带out类型,有返回无参
4、既带in又带out,有返回有参
5、带inout,有返回有参
注意:in、out、inout都可以在一个存储过程中带多个

创建存储过程

应用:常用于增删改,涉及多条数据的增删改。 而函数用来做查询。

语法:

create procedure 存储过程名(in|out|inout 参数名  参数类型,...)
begin
    存储过程体

end

类似于方法:

修饰符 返回类型 方法名(参数类型 参数名,...){

    方法体;
}

注意

  1. 存储过程中每条存储语句中都要有分号。通过设置结束标志来判断什么时候结束。

  2. 设置完结束符以后,结束符就是设置的字符了,因此以后的SQL语句的结束符就是设置的字符,如果需要的话需要针对性再改。

  3. 设置的新的结束标记仅针对一次连接。

    1、需要设置新的结束标记
    delimiter 新的结束标记
    示例:
    delimiter $
    set @name$ # 作为存储过程的返回值
    CREATE PROCEDURE 存储过程名(IN|OUT|INOUT 参数名 参数类型,…)
    BEGIN

     sql语句1;
     sql语句2;
    

    END $
    SELECT @name$ # 查询返回值的内容。

    2、存储过程体中可以有多条sql语句,如果仅仅一条sql语句,则可以省略begin end

    3、参数前面的符号的意思
    in:该参数只能作为输入 (该参数不能做返回值)
    out:该参数只能作为输出(该参数只能做返回值)
    inout:既能做输入又能做输出,重新赋值后,参数值就会发生改变。

注:

  1. OUT参数的值在存储过程执行结束之后会自动返回。因此需要在内部将结果付给存储变量,在外部定义用户变量传入才能出过程调用时的参数,然后方便后面使用。

调用存储过程

call 存储过程名(实参列表)

删除存储过程

DROP PROCEDURE 存储过程名; 删除存储过程,只能一个一个删

查案存储过程

SHOW CREATE PROCEDURE 存储过程名; 查看存储过程的信息

没有更新存储过程的命令。

九、函数

特点

  1. 函数的特点与存储过程相同,
  2. 函数有且仅有一个返回值。
  3. 区别于存储过程,函数用于对查询的封装。

创建函数

学过的函数:LENGTH、SUBSTR、CONCAT等
语法:

CREATE FUNCTION 函数名(参数名 参数类型,...) RETURNS 返回类型
BEGIN
    函数体

END

调用函数

调用函数,并显示查询的结果。

SELECT 函数名(实参列表)

函数和存储过程的区别

        关键字        调用语法    返回值            应用场景
函数        FUNCTION    SELECT 函数()    只能是一个        一般用于查询结果为一个值并返回时,当有返回值而且仅仅一个
存储过程    PROCEDURE    CALL 存储过程()    可以有0个或多个        一般用于更新

十、流程控制结构

系统变量

一、全局变量

作用域:针对于所有会话(连接)有效,但不能跨重启

查看所有全局变量
SHOW GLOBAL VARIABLES;
查看满足条件的部分系统变量
SHOW GLOBAL VARIABLES LIKE '%char%';
查看指定的系统变量的值
SELECT @@global.autocommit;
为某个系统变量赋值
SET @@global.autocommit=0;
SET GLOBAL autocommit=0;

二、会话变量

作用域:针对于当前会话(连接)有效

查看所有会话变量
SHOW SESSION VARIABLES;
查看满足条件的部分会话变量
SHOW SESSION VARIABLES LIKE '%char%';
查看指定的会话变量的值
SELECT @@autocommit;
SELECT @@session.tx_isolation;
为某个会话变量赋值
SET @@session.tx_isolation='read-uncommitted';
SET SESSION tx_isolation='read-committed';

自定义变量

一、用户变量

声明并初始化:

SET @变量名=值;
SET @变量名:=值;
SELECT @变量名:=值;

赋值:

方式一:一般用于赋简单的值
SET 变量名=值;
SET 变量名:=值;
SELECT 变量名:=值;


方式二:一般用于赋表 中的字段值
SELECT 字段名或表达式 INTO 变量
FROM 表;

使用:

select @变量名;

二、局部变量

声明:

declare 变量名 类型 【default 值】;

赋值:

方式一:一般用于赋简单的值
SET 变量名=值;
SET 变量名:=值;
SELECT 变量名:=值;


方式二:一般用于赋表 中的字段值
SELECT 字段名或表达式 INTO 变量
FROM 表;

使用:

select 变量名

二者的区别:

        作用域            定义位置        语法

用户变量 当前会话 会话的任何地方 加@符号,不用指定类型
局部变量 定义它的BEGIN END中 BEGIN END的第一句话 一般不用加@,需要指定类型

分支

一、if函数
语法:if(条件,值1,值2)
特点:可以用在任何位置

二、case语句

语法:

情况一:类似于switch
case 表达式
when 值1 then 结果1或语句1(如果是语句,需要加分号) 
when 值2 then 结果2或语句2(如果是语句,需要加分号)
...
else 结果n或语句n(如果是语句,需要加分号)
end 【case】(如果是放在begin end中需要加上case,如果放在select后面不需要)

情况二:类似于多重if
case 
when 条件1 then 结果1或语句1(如果是语句,需要加分号) 
when 条件2 then 结果2或语句2(如果是语句,需要加分号)
...
else 结果n或语句n(如果是语句,需要加分号)
end 【case】(如果是放在begin end中需要加上case,如果放在select后面不需要)

特点:

1. 可以用在任何位置
 2. ELSE 可以省略
 3. 满足条件后,执行THEN 后的语句,然后直接跳出。

三、if elseif语句

语法:

if 情况1 then 语句1;
elseif 情况2 then 语句2;
...
else 语句n;
end if;

特点:
只能用在begin end中!!!!!!!!!!!!!!!

三者比较:
应用场合
if函数 简单双分支
case结构 等值判断 的多分支
if结构 区间判断 的多分支

循环

语法:

【标签:】WHILE 循环条件  DO
    循环体
END WHILE 【标签】;

特点:

只能放在BEGIN END里面

如果要搭配leave跳转语句,需要使用标签,否则可以不用标签

leave类似于java中的break语句,跳出所在循环!!!

本文为作者原创文章,未经作者允许不得转载。

...

...

00:00
00:00