MySQL 进阶之路(三)事务控制

事务
事务的ACID(acid)属性
➢1. 原子性( Atomicity)
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。

➢2.一 致性( Consistency)
事务必须使数据库从一个- -致性状态变换到另外-一个一致性状态。

➢3.隔离性(Isolation)
事务的隔离性是指- 一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。

➢4.持久性( Durability)
持久性是指一一个事务一 旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响

事务的创建
隐式事务:事务没有明显的开启和结束的标记
比如insert、update、 delete语 句
delete from 表 where id =1;
显式事务:事务具有明显的开启和结束的标记
前提:必须先设置自动提交功能为禁用
set autocommit=0;
查看自动提交是否开启
SHOW VARIABLES LIKE ’ autocommit ’ ;
演示事务的使用步骤
#开启事务
SET autocommit=0;
START TRANSACTI ON;

#编写一组事务的语句
UPDATE account SET balance = 1000 WHERE username= 张无忌,;
UPDATE account SET balance = 1000 WHERE use rname= "赵敏”;

结束事务
ROLLBACK;
#commit;

事务隔离级别

| |

隔离级别 描述
READ UNCOMMTTED(读未提交数据) 允许事务读取未被其他事物提交的变更脏读,不可重复读和幻读的问题都会出现
READ COMMTED(读已提交数据) 只允许事务读取已经被其它事务提交的变更.可以避免脏读,但不可重复读和幻读问题仍然可能出现
REPEATABLE READ(可重复读) 确保事务可以多次从一个字段中读取相同的值在这个事务持续期问,禁止其他事物对这个字段进行更新.可以避免脏读和不可重复读,但幻读的问题仍然存在.
SERIALIZABLE(串行化) 确保事务可以从一个表中读取相同的行在这个事务持续期问,禁止其他事务对该表执行插大.更新和删除操作.所有并发问题都可以避免,但性能十分低下.

➢脏读:对于两个事务T1,T2, T1读取了已经被T2更新但还没有被提交的字段.之后,若T2回滚,T1读取的内容就是临时且无效的.

➢不可重复读:对于两个事务T1, T2,T1读取了一个字段,然后T2更新了该字段.之后, T1再次读取同一个字段,值就不同了。

➢幻读:对于两个事务T1, T2, T1从一个表中读取了一个字段,然后T2在该表中插入了一些新的行.之后,如果T1再次读取同一个表,就会多出几行.

对于同时运行的多个事务,当这些事务访问数据库中相同的数据时,如果没有采取必要的隔离机制,就会导致各种并发问题:

数据库事务的隔离性:数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题.

一个事务与其他事务隔离的程度称为隔离级别.数据库规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一 致性就越好,但并发性越弱.

每启动-一个mysql程序,就会获得一个单独的数据库连接.每个数据库连接都有一.个全局变量@@tx_isolation,表示当前的事务隔离级别.

查看当前的隔离级别: SELECT @@tx_ _isolation;

隔离级别 脏读 不可重复读 幻读
read uncommitted V V V
read committed x V V
repeatable read x x V
serializable x x x

设置当前mySQL连接的隔离级别:
➢set transaction isolation level read committed;

设置数据库系统的全局的隔离级别:
➢set global transaction isolation level read committed;

mysq1中默认第三个隔高级别 repeatable read
oracle中默认第二个隔高级别 read committed
savepoint
#3.演示savepoint的使用
SET autocomnit=0;
START TRANSACTION;
DELETE FROM account WHERE id=25p
SAVEPOINT a;#设置保存点
DELETE FROM account WHERE id=28;
ROLLBACK TO a;单 回滚到保存点

视图
含义:虚拟表,和普通表一样使用
mysq15.1版本 出现的新特性,是通过表动态生成的数据
重用sql语句
简化复杂的sql操作,不必知道它的查询细节
保护数据,提高安全性
$案例:查询姓张的学生名和专业名
SELECT s tuname , majorname
FROM stuinfo s
INNER JOIN major m ON s. 'majorid'= m.'id'
WHERE s.‘stuname’ LIKE '%张%' ;

创建视图
CREATE VIEW v1
AS
SELECT stuname , maj orname
FROM stuinfo s
INNER JOIN major m ON s.'majorid'= m. id ;
SELECT * FROM v1 WHERE stuname LIKE '张号';

删除视图
DROP VIEW 视图名;

查看试图
DESC 视图名;

变量
一、系统变量,
说明:
变量由系统提供的,不是用户定义,属于服务器层面使用的语法:
注意:
如果是全局级别,则需要加global, 如果是会话级别,则需要加session, 如果不写,则默认session

1、查看所有的系统变量
show global 【session】 variables;
2、查看满足条件的部分系统变量
show globaI 【session】 variables like ’%char%‘;
3、查看指定的某个系统变量的值
select @@global 【session】 . 系统变量名;
4、为某个系统变量赋值
方式一;
set globall 【session】 系统变量名 =值;
方式二:
set eglobal【session】 .系统变量名=值;
》 全局变量

#①查看所有的全局变量
SHOW GLOBAL VARIABLES ;

#②查看部分的全局变量
SHOW GLOBAL VARIABLES LIKE '%char%' ;

#③查看指定的全局变量的值
SELECT B@global . autocommit ;
SELECT @@tx_isolation;

#④为某个指定的全局变量赋值
SET @@global . autocommit=0;

#1》 全局变量
作用域:服务器每次启动将为所有的全局变量赋初始值,针对于所有的会话(连接)有效,但不能跨重启

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

#①查看所有的会话变量
SHOW VARIABLES ;
SHOW SESSION VARIABLES;
#②查看部分的会话变量
SHOW VARIABLES LIKE ‘%chark%’ ;
SHOW SESSION VARIABLES LIKE ‘%char%’ ;
#③查看指定的某个会话变量
SELECT @@tx_isolation;
SELECT @@session.tx_isolation;
#④为某个会话变量赋值
方式一:
SET @@tx_isolation= ’ read-uncommitted’ ;
方式二:
SET SESSION tx_isolation ='read-comnitted ’ ;
自定义变量
说明:变量是用户自定义的,不是由系统的
使用步骤:
声明
赋值
使用(查看、比较、运算等)
用户变量
作用域:针对于当前会话(连接)有效,同于会话变量的作用域应用在任何地方,也就是begin end 里面或begin end外面

赋值的操作符:= 或 :=

#①声明并初始化
SET @用户变量名 = 值;或
SET @用户变量名 := 值;或
SELECT @用户变量名 := 值;

#②赋值(更新用户变量的值)
方式一~:通过SET或SELECT
SET @用户变量名=值;或
SET @用户变量名:=值;或
SELECT B用户变量名:=值;
方式二:通过SELECT INTO
SELECT字段~ INTO变量名 FROM 表 ;
#案例:
#声明并初始化
SET
@name= "john';
SET @name=100;
SET Bcount=1 ;

#赋值
SELECT COUNT (*) INTO @count
FROM employees ;

#查看
SELECT @count ;

#③使用
SELECT 局部变量名;

局部变量
作用域:仅仅在定义它的begin end中有效

应用在begin end中的第一句话I

#①声明
DECLARE变量名类型;
DECLARE变量名类型DEFAULT 值;

#②赋值
方式一:通过sET或SELECT
SET局部变量名=值;或
SET局部变量名:=值;或
SELECT @局部变量名:= 值; ,
方式二:通过SELECT INTO
SELECT 字段 INTo 局部变量名 FROM表;

对比用户变量和局部变量:

变量 作用域 定义和使用的位置 语法
用户变量 当前会话 会话中的任何地方 必须加@符号,不用限定类型
局部变量 BEGIN END中 只能在BEGIN END中,且为第一句话 一般不用加@符号,需要限定类型

#案例:声明两个变量并赋初始值,求和,并打印

#1.用户变量
SET @m=1;
SET @n=2 ;
SET @sum = @m+@n;
SELECT G sum;

存储过程
含义:一组预先编译好的SQL语句的集合,理解成批处理语句
1、提高代码的重用性
2、简化操作
3、减少了编译次数并且减少了和数据库服务器的连接次数,提高了效率
一、创建语法
CREATE PROCEDURE 存储过程名(参数列表)
BEGIN
存储过程体(一組合法的SQL语句)
END

注意:
1、参数列表包含三部分
参数模式 ---- 参数名 ----- 参数类型
举例:
IN stuname VARCHAR (20)

参数模式:
IN:该参数可以作为输入,也就是该参数需要调用方传入值
OUT: 该参数可以作为输出,也就是该参数可以作为返回值
INOUT:该参数既可以作为输入又可以作为输出,也就是该参数既需要传入值,又可以返回值

2、如果存储过程体仅仅只有一-句话,BEGIN END可以省略

存储过程体中的每条SQL语句的结尾要求必须加分号。
存储过程的结尾可以使用DELIMITER 重新设置
语法:
DELIMITER 结束标记
案例:
DELIMITER $
1、创建无参的存储过程
DELIMITER $
CREATE PROCEDURE myp1 ()
BEGIN
INSERT INTO admin (use rname, 'pas sword ' )
VALUES('john1", 0000), (lily', 0000'), ('rose', 0000"), ("jack", *0000"), ('tom', '0000') ;
END $

#调用
CALL myp1 () S

2、创建带 in 模式参数的存储过程

#案例1:创建存储过程实现根据女神名,查询对应的男神信息
CREATE PROCEDURE myp2 (IN beautyName VARCHAR (20) )
BEGIN
SELECT bo.*
FROM boys bo
RIGHT JOIN beauty b ON bo.id = b.boyfriend_ id
WHERE b.name= beautyName ;
END $

#调用
CALI myp2 ("柳岩')$

#案例2 :创建存储过程实现,用户是否登录成功
CREATE PROCEDURE myp4 (IN username VARCHAR(20) , IN PASSWORD VARCHAR (20) )
BEGIN
DECLARE result INT DEFAULT 0;#声明并初始化
SELECT COUNT(*) INTO result#赋 值
FROM admin
WHERE admin. username = use rname
AND admin. password = PASSWORD;
SELECT IE (result>0, '成功',‘失败');#使用
END $

#调用
CALL myp3('张飞', *8888')$

3、创建带out模式的存储过程
#案例1:根据女神名,返回对应的男神名
CREATE PROCEDURE myp5 (IN beautyName VARCHAR(20) , OUT boyName VARCHAR (20) )
BEGIN
SELECT bo. boyName INTO boyName
FROM boys bo
INNER JOIN beauty b ON bo.id = b.boyfriend_ id
WHERE b. name =beautyName;
END $

#调用
CALL myp5 ("小昭" , @bName) $
SELECT @bNameS

#案例2:根据女神名,返回对应的男神名和男神魅力值
CREATE PROCEDURE myp6 (IN beautyName VARCHAR(20) , OUT boyName VARCHAR(20) , OUT userCP INT )
BEGIN
SELECT bo.boyNase ,bo.usexCP INTo boyName , userCP
PROM boys bo
INNER JOIN beauty b ON bo.id = b.boyfriend_ id
WHERE b . name = beautyName ;
END $

#调用
CALL myp6(*小昭", @bName, Busercp)$

#4.创建带inout模式参数的存储过程
#案例1:传入a和b两个值,最终a和b都翻倍并返回
CREATE PROCEDURE myp8 (INOUT a INT , INOUT b INT)
BEGIN
SET a=a2;
SET b=b
2;
END $
#调用
SET @m=10$
SET @n=20$
CALL myp8 (@m, @n) S
SELECT @m, @n $

二、删除存储过程
#语法: drop procedure 存储过程名
DROP PROCEDURE p1 ;
DROP PROCEDURE p2,p3;#x (错误)

三、查看存储过程的信息
DESC myp2;x(错误)
SHOW CREATE PROCEDURE myp2 ;

函数
一、创建语法
CREATE FUNCTION 函数名(参数列表) RETURNS 返回类型
BEGIN
函数体
END

注意:
1.参数列表包含两部分:
参数名参数类型
2.函数体:肯定会有return语句, 如果没有会报错
如果return语句没有放在函数体的最后也不报错,但不建议
return值;
3.函数体中仅有一句话,则可以省略begin end
4.使用delimiter语句设置结束标记

----------------------------案例演示----------------------------

#1.无参有返回
#案例:返回公司的员工个数
CREATE FUNCTION myf1 () RETURNS INT
BEGIN
DECLARE c INT DEFAULT 0;定义变量
SELECT COUNT (*)
INTO c
FROM employees ;
RETURN C;
LEND $

SELECT myf1 ()$

#2.有参有返回
#案例1:根据员工名,返回它的工资
CREATE FUNCTION myf2 (empName VARCHAR(20)) RETURNS DOUBLE
BEGIN
SET @sal=0;#定义用户变量
SELECT salary INTO @sal #赋直
FROM employees
WHERE last name = empName ;
RETURN tsal ;
END $
SELECT myf2('k_ing') $

#案例2:根据部门名,返回该部门的平均工资
CREATE FUNCTION myf3 (deptName VARCHAR(20)) RETURNS DOUBLE
BEGIN
DECLARE sal DOUBLE;
SELECT AVG (salary) INTO sal
FROM employees e
JOIN departments d ON e . department_id = d.departmentid
WHERE d. department
name = deptName;
RETURN sal ;
END $
SELECT myf3('IT')$

一、创建函数,实现传入两个float,返回二者之和
CREATE FUNCTION test_ fun1 (num1 FLOAT, num2 FLOAT) RETURNS FLOAT
BEGIN
DECLARE SUM FLOAT DEFAULT 0;
SET SUM=num1+num2 ;
RETURN SUM;
END $

SELECT test_ fun1 (1,2)$

*三、查看函数
SHOW CREATE FUNCTION myf3;
#四、删除函数
DROP FUNCTION myf3;[

猜你喜欢

转载自blog.51cto.com/14509987/2434178
今日推荐