MySQL之视图、触发器、事务、索引及其他知识补充

一、视图

视图是将SQL语句的查询结果当做虚拟表实体化保存起来,以后可以反复使用

create view teacher2course as
select * from teacher inner join course on teacher.tid = course.teacher_id;

drop view teacher2course;
-- 视图使用频率不高

二、触发器(trigger)

触发器:满足特点条件之后自动执行。
在MySQL只有三种情况下可以触发:

  • 针对表的增
  • 增前
  • 增后
  • 针对表的改
  • 改前
  • 改后
  • 针对表的删
  • 删前
  • 删后

语法结构

create trigger 触发器的名字 before/after insert/update/delete on 表名 for each row
begin
    sql语句
end

触发器名字在命名的时候推荐使用如下方式:

tri_after_insert_t1、tri_before_delete_t1

如何临时修改SQL语句的结束符:

delimiter $$

在MySQL中NEW特指数据对象可以通过点的方式获取字段对应的数据

id    name  pwd  hobby
1     jason  123  read
NEW.name  >>>  jason

案例:

CREATE TABLE cmd (
    id INT PRIMARY KEY auto_increment,
    USER CHAR (32),
    priv CHAR (10),
    cmd CHAR (64),
    sub_time datetime,   -- 提交时间
    success enum ('yes', 'no')   -- 0代表执行失败
);

CREATE TABLE errlog (
    id INT PRIMARY KEY auto_increment,
    err_cmd CHAR (64),
    err_time datetime
);

delimiter $$  -- 将mysql默认的结束符由;换成$$
create trigger tri_after_insert_cmd after insert on cmd for each row
begin
    if NEW.success = 'no' then  -- 新记录都会被MySQL封装成NEW对象
        insert into errlog(err_cmd,err_time) values(NEW.cmd,NEW.sub_time);
    end if;
end $$
delimiter ;  -- 结束之后记得再改回来,不然后面结束符就都是$$了

-- 往表cmd中插入记录,触发触发器,根据IF的条件决定是否插入错误日志
INSERT INTO cmd (
    USER,
    priv,
    cmd,
    sub_time,
    success
)
VALUES
    ('tony','0755','ls -l /etc',NOW(),'yes'),
    ('tony','0755','cat /etc/passwd',NOW(),'no'),
    ('tony','0755','useradd xxx',NOW(),'no'),
    ('tony','0755','ps aux',NOW(),'yes');

-- 查询errlog表记录
select * from errlog;
-- 查看触发器
show triggers;
-- 删除触发器
drop trigger tri_after_insert_cmd;

三、事务(重要)

  • A:原子性 每个事务都是不可分割的最小单位(同一个事务内的多个操作要么同时成功要么同时失败)
  • C:一致性 事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
  • I:隔离性 事务与事务之间彼此不干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
  • D:持久性 持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的;接下来的其他操作或故障不应该对其有任何影响
start transcation;  -- 开启事务
    诸多SQL操作
rollback;  -- 回滚到操作之前的状态
commit;  -- 确认事务操作,之后不能回滚

示例如下 :

create table user(
id int primary key auto_increment,
name char(32),
balance int
);

insert into user(name,balance)
values
('jason',1000),
('egon',1000),
('tank',1000);

-- 修改数据之前先开启事务操作
start transaction;

-- 修改操作
update user set balance=900 where name='jason';   -- 买支付100元
update user set balance=1010 where name='egon';   -- 中介拿走10元
update user set balance=1090 where name='tank';   -- 卖家拿到90元

-- 回滚到上一个状态
rollback;

-- 开启事务之后,只要没有执行commit操作,数据其实都没有真正刷新到硬盘
commit;
"""开启事务检测操作是否完整,不完整主动回滚到上一个状态,如果完整就应该执行commit操作"""

站在python代码的角度,应该实现的伪代码逻辑:

try:
    update user set balance=900 where name='jason'; #买支付100元
    update user set balance=1010 where name='egon'; #中介拿走10元
    update user set balance=1090 where name='tank'; #卖家拿到90元
except 异常:
    rollback;
else:
    commit;

四、存储过程

类似于python中的自定义函数。

delimiter $$
create procedure p1()
begin
    select * from user;
end $$
delimiter ;
-- 调用
call p1();
delimiter $$
create procedure p2(
    in m int,  -- in表示这个参数必须只能是传入不能被返回出去
    in n int,
    out res int  -- out表示这个参数可以被返回出去,还有一个inout表示即可以传入也可以被返回出去
)
begin
    select * from user where id > m and id < n;
    set res=0;  -- 用来标志存储过程是否执行
end $$
delimiter ;
import pymysql

conn = pymysql.connect(
    host='127.0.0.1',
    port=3306,
    user='root',
    passwd='456852',
    db='db6',
    charset='utf8',
    autocommit=True
)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.callproc('p2',(1,3,10))
@_p1_0=1,@_p1_1=3,@_p1_2=10;
print(cursor.fetchall())

五、函数

相当于Python中的内置函数。

ps:可以通过 help &#x51FD;&#x6570;&#x540D; 查看帮助信息!

  • 移除指定字符
Trim()、LTrim()、RTrim()
  • 大小写转换
Lower()、Upper()
  • 获取左右起始指定个数字符
Left()、Right()
  • 返回读音相似值
Soundex()

"""
eg:
客户表中有一个顾客登记的用户名为J.Lee
但如果这是输入错误真名其实叫J.Lie,可以使用soundex匹配发音类似的
where Soundex(name)=Soundex('J.Lie')
"""

  • 日期格式
date_format()

'''在MySQL中表示时间格式尽量采用2022-11-11形式'''
CREATE TABLE blog (
    id INT PRIMARY KEY auto_increment,
    NAME CHAR (32),
    sub_time datetime
);
INSERT INTO blog (NAME, sub_time)
VALUES
    ('第1篇','2015-03-01 11:31:21'),
    ('第2篇','2015-03-11 16:31:21'),
    ('第3篇','2016-07-01 10:21:31'),
    ('第4篇','2016-07-22 09:23:21'),
    ('第5篇','2016-07-23 10:11:11'),
    ('第6篇','2016-07-25 11:21:31'),
    ('第7篇','2017-03-01 15:33:21'),
    ('第8篇','2017-03-01 17:32:21'),
    ('第9篇','2017-03-01 18:31:21');

select date_format(sub_time,'%Y-%m'),count(id) from blog group by date_format(sub_time,'%Y-%m');

-- 更多日期处理相关函数
where Date(sub_time) = '2015-03-01'
where Year(sub_time)=2016 AND Month(sub_time)=07;
    adddate 增加一个日期
    addtime 增加一个时间
    datediff计算两个日期差值
  ...

六、流程控制

-- if判断
if i = 1 THEN
       SELECT 1;
ELSEIF i = 2 THEN
       SELECT 2;
ELSE
       SELECT 7;
END IF;

-- while循环
SET num = 0 ;
WHILE num < 10 DO
    SELECT
        num ;
    SET num = num + 1 ;
END WHILE ;

七、索引与慢查询优化(重要)

索引可以简单的理解为帮助你加快数据查询速度的工具,也可以把索引比喻成书的目录。

索引的建立涉及到几种数据结构:

  • B树
  • B+树(叶子节点添加了指针)
  • B*树(基于B+树在枝节点也添加了指针)

将某个字段添加成索引就相当于依据该字段建立了一颗B+树,从而加快查询速度。

如果某个字段没有添加索引,那么依据该字段查询数据会非常的慢(遍历查找)。

注意外键 foreign key 不是索引,它仅仅是用来创建表与表之间关系的。

-- 创建唯一索引需要提前排查是否有重复数据
select count(字段) from 表名;
select count(distinct(字段)) from 表名;

-- 查看当前表内部索引值
show index from 表名;

-- 创建主键索引
alter table t1 add primary key pri_id(id);

-- 创建唯一索引
alter table t1 add unique key uni_age(age);

-- 创建普通索引
alter table t1 add index idx_name(name);

-- 前缀索引(属于普通索引)
"""
避免对大列建索引,如果有就使用前缀索引
eg:博客内容 百度搜索内容等
"""
alter table t1 add index idx_name(name(4));

-- 联合索引(属于普通索引,遵循最左匹配原则)
alter table t1 add index idx_all(name,age,sex);

-- 删除索引
alter table t1 drop index 索引名(idx_name、idx_all...);
  • 全表扫描:不走索引,遍历表查找数据,效率极低,生产环境下尽量不要书写类似SQL;
  • 索引扫描:走索引,加快数据查询,建议书写该类型SQL;

explain 就是帮助我们查看SQL语句属于那种扫描。

常见的索引扫描类型:

从上到下,性能从最差到最好,生产环境下认为至少要达到 range级别。

不走索引情况(熟悉四条及以上):

  • 没有查询条件,或者查询条件没有建立索引;
  • 查询结果是原表中的大部分数据(%25以上);
  • 索引本身失效,统计数据不真实;
  • 查询条件使用函数在索引列上或者对索引列进行运算,运算包括(+,-,*等);
  • 隐式转换导致索引失败; eg:字段是字符串类型,查询使用整形
  • <> &#xFF0C;not in不走索引 单独的>,
  • like "%_" 百分号在最前面不走;
  • 单独引用联合索引里非第一位置的索引列(不遵循最左匹配原则);

索引的创建会加快数据的查询速度,但是一定程度会拖慢数据的插入和删除速度。

八、隔离级别

在SQL标准中定义了四种隔离级别,每一种级别都规定了一个事务中所做的修改。

InnoDB支持所有隔离级别: set transaction isolation level

  • read uncommitted(未提交读) 事务中的修改即使没有提交,对其他事务也都是可见的,事务可以读取未提交的数据,这一现象也称之为 "&#x810F;&#x8BFB;"
  • read committed(提交读)—大多数数据库系统默认的隔离级别 一个事务从开始直到提交之前所作的任何修改对其他事务都是不可见的,这种级别也叫做 "&#x4E0D;&#x53EF;&#x91CD;&#x590D;&#x8BFB;"
  • repeatable read(可重复读)—MySQL默认隔离级别 能够解决 "&#x810F;&#x8BFB;"问题,但是无法解决 "&#x5E7B;&#x8BFB;" 所谓 "&#x5E7B;&#x8BFB;"指的是当某个事务在读取某个范围内的记录时另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录会产生幻行,InnoDB和XtraDB通过多版本并发控制(MVCC)及间隙锁策略解决了该问题。
  • serializable(可串行读) 强制事务串行执行,很少使用该级别

Original: https://www.cnblogs.com/JZjuechen/p/15929882.html
Author: JZEason
Title: MySQL之视图、触发器、事务、索引及其他知识补充

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/609858/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • docker部署安装Nginx

    docker部署安装Nginx 前言 Nginx是一个高性能的HTTP和反向代理web服务器,同事也提供了IMAP/POP3/SMTP服务。特点: 轻量级的Web服务器/反向代理服…

    Linux 2023年6月6日
    096
  • 第2次作业:支付宝案例分析

    1.介绍产品相关信息 *你选择的产品是? 支付宝 *为什么选择该产品作为分析? 在使用支付宝前,像交学费这种金额比较大的金钱来往都得去银行处理,在银行排队通常需要很多时间,尤其是办…

    Linux 2023年6月8日
    086
  • MySQL之变量

    mysql变量分类: 系统变量:系统自带的变量 状态变量:用于设置或保存系统的运行状态 用户自定义变量:用户自定义的变量 系统变量 使用@@标识一个系统变量,系统变量分为全局(gl…

    Linux 2023年6月7日
    0118
  • 服务器部署 Vue 和 Django 项目的全记录

    本篇记录我在一个全新服务器上部署 Vue 和 Django 前后端项目的全过程,内容包括服务器初始配置、安装 Django 虚拟环境、python web 服务器 uWSGI 和反…

    Linux 2023年6月7日
    0119
  • 写shell,运行出错:syntax error near unexpected token `$’dor”

    【解决过程】 1.网上搜了下,参考:linux shell脚本报错:syntax error near unexpected token </a></p> …

    Linux 2023年5月28日
    094
  • PYTORCH: 60分钟

    什么是PyTorch? PyTorch 是一个基于Python的科学计算包,有两大用途: NumPy的替代品,可使用GPUs和其它加速器的强大功能 一个用于实现神经网络的自动微分库…

    Linux 2023年6月16日
    0175
  • 建表参数PCTFREE、PCTUSED、INITRANS和MAXTRANS释疑

    PCTFREE与PCTUSED建表时可以指定以上两个参数的值(整数),PCTFREE表示一个块中保留的剩余空间大小百分比,该保留空间主要用于已有记录的更 新操作;PCTUSED表示…

    Linux 2023年6月14日
    092
  • 质量问题不是不爆,时候未到

    没有质量,哪来效率,谈什么成本; 最近大半年,团队以极其曲折的方式,将一个支离破碎的应用从重构的边缘给拉了回来,最终项目回到了正常迭代的节奏中; 年初的时候,运营系统相关人员离职,…

    Linux 2023年6月14日
    091
  • STP 指定端口 根端口 区别和理解

    不多说,先上图,A为指定端口,B为非指定端口。 看本文的网友应该知道根端口和指定端口的选举,但是对指定端口和根端口的理解不清楚。这里我就略过选举过程,直接描述这两者的区别和存在的意…

    Linux 2023年6月6日
    0145
  • mysql group by语句流程是怎么样的

    group by流程是怎么样的 注意点: select id%10 as m, count(*) as c from t1 group by m; group by是用于对数据进行…

    Linux 2023年6月8日
    0102
  • redis开启远程访问

    redis默认只允许本地访问,要使redis可以远程访问可以修改redis.conf 打开redis.conf文件在 NETWORK部分有说明 By default, if no …

    Linux 2023年5月28日
    0162
  • Django 如何获取 Model 字段列表?

    在平时的开发过程中,避免不了需要获取 Model 中的字段列表。 那需要把所有字段都再复制一份吗?这样的话就太麻烦了,而且后期也不好维护。 其实,Django 内置了一个方法,可以…

    Linux 2023年6月7日
    0122
  • 开放平台架构指南

    1.前言 2010年前,大型社交网站如腾讯QQ、新浪微博都搭建了开放平台。中小型互联网公司接入开放平台,能够获取社交平台的海量用户,有效的降低获客成本,获得社交平台的其他能力。对于…

    Linux 2023年6月6日
    081
  • Golang 实现 Redis(8): TCC分布式事务

    本文是使用 golang 实现 redis 系列的第八篇, 将介绍如何在分布式缓存中使用 Try-Commit-Catch 方式来解决分布式一致性问题。 在上一篇文章中我们使用一致…

    Linux 2023年5月28日
    095
  • Redis 基础

    Redis 基础 Redis 定位 – 特性 关系型数据库 特性 非关系型数据库 特性 Redis 特性 Redis 安装 – 启动 – 使用 …

    Linux 2023年6月13日
    0147
  • tomcat

    tomcat 一.简介 二.部署tomcat 一.简介 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场…

    Linux 2023年6月7日
    0110
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球