事务,存储过程
一、事务
1、什么是事务:
数据库事务是指作为单个逻辑工作单元执行的一系列操作(SQL语句)。这些操作要么全部执行,要么全部不执行。
2、为什么要有事务:
经典的银行转账,多条sql语句一起执行,要么一起成功,要么一起失败,单一执行,万一失败不就一方损失了吗?
3、事务特性(4种):
- 原子性 (atomicity):强调事务的不可分割.
- 一致性 (consistency):事务的执行的前后数据的完整性保持一致.
- 隔离性 (isolation):一个事务执行的过程中,不应该受到其他事务的干扰
- 持久性(durability) :事务一旦结束,数据就持久到数据库
4、事务运行模式(3种)
- 自动提交事务:默认事务管理模式。如果一个语句成功地完成,则提交该语句;如果遇到错误,则回滚该语句。
- 显式事务:以BEGIN TRANSACTION显式开始,以COMMIT或ROLLBACK显式结束。
- 隐性事务:当连接以此模式进行操作时,sql将在提交或回滚当前事务后自动启动新事务。无须描述事务的开始,只需提交或回滚每个事务。它生成连续的事务链。
例:
1 create table user( 2 id int primary key auto_increment, 3 name char(32), 4 balance int 5 ); 6 7 insert into user(name,balance) 8 values 9 ('老李',999), 10 ('老张',999), 11 ('老朱',999); 12 13 #原子操作 14 start transaction; 15 update user set balance=899 where name='wsb'; #买支付100元 16 update user set balance=1009 where name='egon'; #中介拿走10元 17 update user set balance=1089 where name='ysb'; #卖家拿到90元 18 commit; 19 20 #出现异常,回滚到初始状态 21 start transaction; 22 update user set balance=899 where name='wsb'; #买支付100元 23 update user set balance=1009 where name='egon'; #中介拿走10元 24 uppdate user set balance=1089 where name='ysb'; #卖家拿到90元,出现异常没有拿到 25 rollback; 26 commit; 27 mysql> select * from user; 28 +----+------+---------+ 29 | id | name | balance | 30 +----+------+---------+ 31 | 1 | wsb | 999 | 32 | 2 | egon | 999 | 33 | 3 | ysb | 999| 34 +----+------+---------+ 35 3 rows in set (0.00 sec)
在pymysql中:
1 try: 2 cursor.execute(sql_1) 3 cursor.execute(sql_2) 4 cursor.execute(sql_3) 5 except Exception as e: 6 connect.rollback() # 事务回滚 7 print('事务处理失败', e) 8 else: 9 connect.commit() # 事务提交 10 print('事务处理成功', cursor.rowcount)# 关闭连接 11 cursor.close() 12 connect.close()
总结:事务用于将某些操作的多个SQL作为原子性操作,一旦有某一个出现错误,即可回滚到原来的状态,从而保证数据库数据完整性。
二、存储过程
1、 介绍
存储过程包含了一系列可执行的sql语句,存储过程存放于MySQL中,通过调用它的名字可以执行其内部的一堆sql
使用存储过程的优点:
#1. 用于替代程序写的SQL语句,实现程序与sql解耦 #2. 基于网络传输,传别名的数据量小,而直接传sql数据量大
使用存储过程的缺点:
#1. 程序员扩展功能不方便
补充:程序与数据库结合使用的三种方式
1 #方式一: 2 MySQL:存储过程 3 程序:调用存储过程 4 5 #方式二: 6 MySQL: 7 程序:纯SQL语句 8 9 #方式三: 10 MySQL: 11 程序:类和对象,即ORM(本质还是纯SQL语句)
创建简单存储过程(无参)
1 delimiter // 2 create procedure p1() 3 BEGIN 4 select * from blog; 5 INSERT into blog(name,sub_time) values("xxx",now()); 6 END // 7 delimiter ; 8 9 #在mysql中调用 10 call p1() 11 12 #在python中基于pymysql调用 13 cursor.callproc('p1') 14 print(cursor.fetchall())
创建存储过程(有参)
对于存储过程,可以接收参数,其参数有三类: #in 仅用于传入参数用 #out 仅用于返回值用 #inout 既可以传入又可以当作返回值
1 delimiter // 2 create procedure p2( 3 in n1 int, 4 in n2 int 5 ) 6 BEGIN 7 8 select * from blog where id > n1; 9 END // 10 delimiter ; 11 12 #在mysql中调用 13 call p2(3,2) 14 15 #在python中基于pymysql调用 16 cursor.callproc('p2',(3,2)) 17 print(cursor.fetchall())
out
1 delimiter // 2 create procedure p3( 3 in n1 int, 4 out res int 5 ) 6 BEGIN 7 select * from blog where id > n1; 8 set res = 1; 9 END // 10 delimiter ; 11 12 #在mysql中调用 13 set @res=0; #0代表假(执行失败),1代表真(执行成功) 14 call p3(3,@res); 15 select @res; 16 17 #在python中基于pymysql调用 18 cursor.callproc('p3',(3,0)) #0相当于set @res=0 19 print(cursor.fetchall()) #查询select的查询结果 20 21 cursor.execute('select @_p3_0,@_p3_1;') #@p3_0代表第一个参数,@p3_1代表第二个参数,即返回值 22 print(cursor.fetchall())
inout
1 delimiter // 2 create procedure p4( 3 inout n1 int 4 ) 5 BEGIN 6 select * from blog where id > n1; 7 set n1 = 1; 8 END // 9 delimiter ; 10 11 #在mysql中调用 12 set @x=3; 13 call p4(@x); 14 select @x; 15 16 17 #在python中基于pymysql调用 18 cursor.callproc('p4',(3,)) 19 print(cursor.fetchall()) #查询select的查询结果 20 21 cursor.execute('select @_p4_0;') 22 print(cursor.fetchall())
执行存储过程
1 -- 无参数 2 call proc_name() 3 4 -- 有参数,全in 5 call proc_name(1,2) 6 7 -- 有参数,有in,out,inout 8 set @t1=0; 9 set @t2=3; 10 call proc_name(1,2,@t1,@t2) 11 12 执行存储过程
删除存储过程
drop procedure proc_name;
每天逼着自己写点东西,终有一天会为自己的变化感动的。这是一个潜移默化的过程,每天坚持编编故事,自己不知不觉就会拥有故事人物的特质的。 Explicit is better than implicit.(清楚优于含糊)