视图、触发器、事务、存储过程、函数、数据备份与恢复、流程控制
时间:2019-03-20
本文章向大家介绍视图、触发器、事务、存储过程、函数、数据备份与恢复、流程控制,主要包括视图、触发器、事务、存储过程、函数、数据备份与恢复、流程控制使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
视图
视图是有一条sql语句的查询结果构成的虚拟表
其不是物理存在的 使用方式与普通表相同
创建视图语法
create [or replace] view view_name as sql 语句;
修改
alter view view_name as sql 语句;
删除
drop view view_name;
视图的作用
1.简化sql语句的编写
案例:
create table student( s_id int(3), name varchar(20), math float, chinese float ); insert into student values(1,'tom',80,70),(2,'jack',80,80),(3,'rose',60,75); create table stu_info( s_id int(3), class varchar(50), address varchar(100) ); insert into stu_info values(1,'二班','安徽'),(2,'二班','湖南'),(3,'三班','黑龙江');
#创建视图包括 编号 学生的姓名和班级 create view stu_view (编号,姓名,班级) as select student.s_id,student.name,stu_info.class from student,stu_info where student.s_id=stu_info.s_id; #查询视图 select * from stu_view;
2.限制可查看的数据
可以使用权限来完成 权限到某个库 的某个一个表的某一个字段
视图的特点:
对于视图的增删改查 都会同步到原始表
每一次视图的查询 本质上都是执行了之前创-建视图时 指定的sql语句
对于原始表的修改 也能在视图中查看到 前提是你修改的数据 包含在创建视图时指定的sql语句中
案例:
create table salary_info( id int primary key, name char(10), salary double, dept char(10) ); insert into salary_info values (1,"刘强东",900000,"市场"), (2,"马云",800090,"市场"), (3,"李彦宏",989090,"财务"), (4,"马化腾",87879999,"财务");
#创建市场部视图 create view info as select * from salary_info where dept='市场'; #查看市场部视图 select * from info;
触发器
是一段与某个表有关的mysql程序
当达到某种条件,触发某个东西的执行
条件:
时间点 before |after
具体事件 update |delete | insert
new|old old new
达到条件后:
自动执行一段mysql程序
删除触发器
语法:
drop trigger trigger_name;
作用:
做一个博客系统
需要在执行更新 自动记录更新时间 以及更新具体内容
总的来说就是可以帮你在一个表被修改时 做一些额外操作
语法:
create trigger name after delete on tablename for each row
begin
# 具体要执行的操作
end
在触发器中有两个隐藏对象
new(新的数据)和old(旧的数据)
案例:
创建一个博客表
id int title char content longtext commit_time timestamp
更新记录表
id int content longtext update_time timestamp b_id int
create table blog(id int primary key auto_increment,content text,b_id int,foreign key(b_id) references blog(id),update_time timestamp); create table blogs(id int primary key auto_increment,content text,b_id int,foreign key(b_id) references blog(id),update_time timestamp);
创建触发器 delimiter // create trigger t1 after update on blog for each row begin insert into update_log values(null,new.content,now(),new.id); end // delimiter ; #查询数据 select *from users;
在blog表发生了update事件时 要自动将更新后的数据插入记录表
# 重定义结束符为//因为触发器中包含;而分号是默认的结束符
案例:
存储的是 什么时间执行了 什么指令 结果是什么?
errlog 表 存储的是 所有执行失败的指令信息
当数据插入cmd表时 判断 如果 success 为no 就将这个信息插入errlog表中
准备数据
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 // create trigger trigger1 after insert on cmd for each row begin if new.success = "no" then insert into errlog values(null,new.cmd,new.sub_time); end if; end// delimiter ;
INSERT INTO cmd ( USER, priv, cmd, sub_time, success ) VALUES ('jerry','0755','ls -l /etc',NOW(),'yes'), ('jerry','0755','cat /etc/passwd',NOW(),'no'), ('jerry','0755','useradd xxx',NOW(),'no'), ('jerry','0755','ps aux',NOW(),'yes');
select *from errlog;
事务
事务是逻辑上一组sql语句的集合
特点是:一个事务的所有sql语句 要么全部执行成功 要么全部失败
事务最强大的地方在于
当发生一些不不可控因素时(断电,系统崩溃,网络中断),可以保住数据是完整的(原子性)
原子性
一个事务是一个整体 不可拆分要么都成功要么都失败
一致性
一个事务无论成功或失败 相关数据的约束一定是完整的
隔离性
与效率息息相关
两个事务之间相互独立
read uncommitted 不做任何隔离,可能脏读(读取到其他事务未提交的数据)
read committed 可以防止脏读,不能防止不可重复(并发修改)和幻读(并发添加和修改)
对同一条记录同一事务的两次查询结果不一致称之为不可重复读
原因是:一个事务在查询数据 另一个事务在添加/删除数据
Repeatable_read 可以防止脏读,不可重复读(加锁保证查询事务和更新事务不能并发),不能防止幻读
insert/delete 和查询事务可以并发执行
Serializable 数据库运行在串行化实现,所有问题都没有,就是性能低
查看当前隔离级别
select * from @@tx_isolation
设置新的隔离级别
set global transaction isolation level Serializable
永久性
一个事务一旦提交,就是永久性的 无法回滚
事务在pymysql中的使用
pymysql封装了事务的开启 我们需要做的就是在执行成功后提交事务
一些客户端中默认是没有事务的 例如cmd中的mysql客户端
注意:如果在创建连接时 将自动提交设置为了True则不会再开启事务一般不要改这个默认选项
import pymysql conn = pymysql.connect(host='127.0.0.1', user='root', password='123321', database='day45') cursor = conn.cursor(pymysql.cursors.DictCursor) try: sql1 = 'update account set money=money-100 where id=1' sql2 = 'update account set money=money+100 where id=2' cursor.execute(sql1) cursor.execute(sql2) conn.commit() print('转账成功!') except Exception as e: print(type(e), e) # cursor.scroll()#发生错误就回滚
存储过程
一个存储过程中包含任意sql语句,以及流程控制,事务等待。。。
简单的就是说 将一系列较为复杂的逻辑封装到了mysql中
好处:
例如注册功能
接收用户名 密码
判断用户名是否存在 需要编写一条sql语句 传给服务器 服务器执行完毕返回结果
客户端在发起请求 把用户名和密码穿给服务器
经历了至少2次网络传输
如果使用存储过程就可以一次性将用户名和密码传给服务器等到接收结果即可
降低了网络传输 提高了效率
弊端:学习成本高,运营成本高,沟通成本高 三高
正常开发中有三种常见方式完成数据库相关操作
1.应用程序开发者 只关注逻辑 数据相关的逻辑交给存储过程
优点:优化了网络传输 耦合度降低
弊端:学习成本高,运营成本高,沟通成本高 三高 存储过程移植性非常差每种数据语法都不同
2.应用程序开发者 不仅关注业务逻辑 还需要编写原生的sql语句
优点:一个负责人所有 没有沟通成本
缺点:sql语句编写繁琐 导致开发效率降低
3.应用程序开发者 仅关注业务逻辑 把sql语句相关的交给ORM(对象关系隐射 帮你封装了增删改查 自动生成sql语句)
优点:开发效率提高了
缺点:执行效率较低
摩尔定律 每过18个月 cpu 计算能力 至少翻一番
create procedure p1(type 参数名 数据类型) type :in 输入参数 out输出参数 inout既能输出又能输入 delimiter // create procedure p1(in a double,in b double) begin select *from account where money >= a and money <= b; end// delimiter ;
存储过程 与函数的区别
函数仅仅是一个单纯工具 与数据无关 所以函数中不能出现sql语句
存储过程 既可以包含mysql的逻辑代码 也能包含sql 语句
delimiter // create procedure p2(in a double,in b double,out res char(20)) begin select *from account where money >= a and money <= b; set res = "success"; end// delimiter ;
#删除 drop procedure 过程名称; #查看所有 select `name` from mysql.proc where db = 'db02' and `type` = 'PROCEDURE';
案例1:
create table student( s_id int(3), name varchar(20), math float, chinese float ); insert into student values(1,'tom',80,70),(2,'jack',80,80),(3,'rose',60,75); create table stu_info( s_id int(3), class varchar(50), address varchar(100) ); insert into stu_info values(1,'二班','安徽'),(2,'二班','湖南'),(3,'三班','黑龙江');
delimiter // create procedure p1(in m int,in n int,out res int) begin select *from student where chinese > m and chinese < n; #select *from student where chineseXXX > m and chinese < n; 修改错误的列名以测试执行失败 set res = 100; end// delimiter ; #调用存储过程 call p1(70,80,@res); #查看执行结果 select @res;
import pymysql #建立连接 conn = pymysql.connect( host="127.0.0.1", user="root", password="admin", database="db02" ) # 获取游标 cursor = conn.cursor(pymysql.cursors.DictCursor) # 调用用存储过程 cursor.callproc("p1",(70,80,0)) #p1为存储过程名 会自动为为每个值设置变量,名称为 @_p1_0,@_p1_1,@_p1_2 # 提取执行结果时否有结果取决于存储过程中的sql语句 print(cursor.fetchall()) # 获取执行状态 cursor.execute("select @_p1_2") print(cursor.fetchone())
模拟转账
delimiter // create PROCEDURE p5(OUT p_return_code char(20)) BEGIN DECLARE exit handler for sqlexception BEGIN # ERROR set p_return_code = "出现异常,回滚!"; rollback; END; # exit 也可以换成continue 表示发生异常时继续执行 DECLARE exit handler for sqlwarning BEGIN # WARNING set p_return_code = "出现警告,回滚!"; rollback; END; START TRANSACTION; update account set money = money - 1000 where id = 1; update account set money = money - 1000 where id = 1; # moneys字段导致异常 COMMIT; # SUCCESS set p_return_code = 0; #0代表执行成功 END // delimiter ; #在mysql中调用存储过程 call p5(@res); select @res;
import pymysql conn = pymysql.connect(host='127.0.0.1', user='root', password='123321', database='day45') cursor = conn.cursor(pymysql.cursors.DictCursor) # 调用存储过程 如果是一个输出out参数 随便给个值就行 # cursor.callproc('p2',(500,2000,0)) # # pymysql会自动定义变量@_存储过程名称_参数索引 # #分别是:@_p2_0 @_p2_1 @_p2_2 # # # 获取结果 # # print(cursor.fetchall()) # # # 获取存储过程的结果 # # cursor.execute('select @_p2_2') # # print(cursor.fetchall()) # 调用 cursor.callproc('p5',(0,)) # 获取结果是否有结果取决于存储过程中是否select语句 print(cursor.fetchall()) # 通过查询变量获取执行状态 cursor.execute('select @_p5_0') print(cursor.fetchall())
函数
内置函数
日期相关
CURRRNT_DATE() | 当前日期 |
CURRENT_TIME() | 当前时间 |
CURRENT_TIMESTAMP | 当前时间戳 |
DATE_ADD(date2,INTERVAL d_value d_type) | 在date2中加上日期或时间 |
DATE_SUB(date2,INTERVAL d_value d_type) | 在date2上减去一个时间 |
DATEDIFF(date1,date2) | 两个日期差(结果是天) |
TIMEDIFF(date1,date2) | 两个时间差(多少小时多少分钟多少秒) |
NOW() | 当前时间 |
YEAR|Month|DATE(datetime) | 返回datetime的某个部分 |
字符串相关
CHARSET(str) | 返回字串字符集 |
CONCAT(string2[,....]) | 连接字串 |
INSTR(string,substring ) | 返回substring在string中出现的位置,没有返回0 |
UCASE(string2) | 转换成大写 |
LCASE(string2) | 装换成小写 |
LEFT(string2,length) | 从string2中的左边起取length个字符 |
LENGTH(string) | string长度 |
REPLACE(str,search_str,replace_str) | 在str中replace_str替换search_str |
STRCMP(string1,string2) | 逐字符比较两字串大小 |
SUBSTRING(str,position[,length]) | 从str的position开始,取length个字符 |
LTRIM(string2)RTRIM(string2)trim | 去除前端空格或后端空格 |
数字相关
ABS(number2) | 绝对值 |
BIN(decimal_number) | 十进制转二进制 |
CEILING(number2) | 向上取整 |
CONV(number2,from_base,to_base) | 进制转换 |
FLOOR(number2) | 向下取整 |
FORMAT(number,decimal_places) | 保留小数位数 |
HEX(DecimalNumber) | 转十六进制 |
LEAST(number,number2[,...]) | 求最小值 |
MOD(numberator) | 求余 |
RAND([seed]) | RAND([seed]) |
其他函数
USER() | 查询用户 |
DATABASE() | 数据库名称 |
MD5(str) | 为字符串算出一个MD5 128比特检查和,通常用于对应用程序使用到表的某个字段(比如用户密码)加密 |
PASSWORD(str) | 从原文密码str计算并返回密码字符串,通过用于对mysql数据库的用户密码加密 |
DATE_FORMAT(str,fmt) | 将一个日期按照某个格式输出 |
自定义函数
#语法 CREATE FUNCTION f_name(paramters) returns dataType; return value;
create function addfuntion(a int,b int) returns int return a + b; 54asd#执行函数 select addfuntion(1,1);
- 将我的 Windows Phone 应用程序更新到 Windows Phone 8
- 绑定子类的泛型基类,反模式?
- 给创业码农的话--如何提升开发效率
- 基于OEA框架的客户化设计(二) 元数据设计
- 自定义actionbar
- (转)JS算法系列-数组去重
- 基于OEA框架的客户化设计(三) “插件式”DLL
- 居中“魔法”总结
- Windows微信DPI适配
- 采用Symbol和process.nextTick实现Promise
- MongoDB 如何使定制电子商务变得简单
- 代码重构之路的艰辛
- 量化投资之机器学习应用——基于 SVM 模型的商品期货择时交易策略(提出质疑和讨论)
- 虚拟串口工具_com0com
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 解析 HashMap源码值概括
- 解析 HashMap 源码之基本操作
- Docker手册
- 小知识:TFA收集日志报错空间不足
- Java SPI 居然这么多知名框架在用
- Ceph 入门到实战之 RBD 块存储接口
- 聊聊 Python 面试最常被问到的几种设计模式(下)
- 带你用 Python 实现自动化群控(入门篇)
- 实战篇 | 基于freeRTOS的多任务事件传输demo(附代码)
- 在kali linux中你应该知道的信息收集姿势(一)
- 【拓展】谈谈字符编码:Unicode编码与emoji表情编码
- TCP/IP 应用层协议解释
- Cisco Packet Tracer服务器模拟搭建
- Python3调用Google翻译
- 打造最强移动测试平台