Day 37 SQL基础(五)

事务处理

事务用于将某些操做的多个SQL做为原子性操做,一旦有某一个出现错误,便可回滚到原来的状态,从而保证数据库数据完整性mysql

开始事务

start transaction程序员

标识事务的开始sql

回滚事务

rollback数据库

用来回退(撤销)SQL语句编程

select * from users;
start transaction;
update users set age = 18 where id = 120;
delete from users where name = 'tiny';
rollback;
select * from users;

rollback只能在一个事务处理内使用,在执行一条start transaction命令以后安全

提交事务

commit服务器

通常的MySQL语句都是直接针对数据库表执行和编写的.这就是所谓的隐含提交,即提交(写或保存)操做是自动进行的.网络

可是.在事务处理块中,提交不会隐含地进行.为进行明确的提交,使用commit语句并发

start transaction;
update users set age = 18 where id = 120;
delete from users where name = 'tiny';
commit;

事务的特性

  • 原子性(Atomicity): 原子意为最小的粒子,即不能再分事务,要么所有执行,要么所有取消
  • 一致性(Consistency): 指事务发生前发生后,数据的总额依然匹配
  • 隔离性(Isolation): 简单点说,某个事务的操做对其余事务是不可见的
  • 持久性(Durability): 当事务完成后,其影响应该保留下来,不能撤销,只能经过'补偿性事务'来抵消以前的错误

存储引擎

什么是存储引擎

MySQL中的数据用各类不一样的技术存储在文件(或者内存)中。这些技术中的每一种技术都使用不一样的存储机制、索引技巧、锁定水平而且最终提供普遍的不一样的功能和能力。经过选择不一样的技术,你可以得到额外的速度或者功能,从而改善你的应用的总体功能。

例如,若是你在研究大量的临时数据,你也许须要使用内存存储引擎。内存存储引擎可以在内存中存储全部的表格数据。又或者,你也许须要一个支持事务处理的数据库(以确保事务处理不成功时数据的回退能力)。

这些不一样的技术以及配套的相关功能在MySQL中被称做存储引擎(也称做表类型)。

MySQL默认配置了许多不一样的存储引擎,能够预先设置或者在MySQL服务器中启用。你能够选择适用于服务器、数据库和表格的存储引擎,以便在选择如何存储你的信息、如何检索这些信息以及你须要你的数据结合什么性能和功能的时候为你提供最大的灵活性。

选择如何存储和检索你的数据的这种灵活性是MySQL为何如此受欢迎的主要缘由。其它数据库系统 (包括大多数商业选择)仅支持一种类型的数据存储

遗憾的是,其它类型的数据库解决方案采起的“一个尺码知足一切需求”的方式意味着你要么就牺牲一些性能,要么你就用几个小时甚至几天的时间详细调整你的数据库。使用MySQL,咱们仅须要修改咱们使用的存储引擎就能够了。

mysql5.6支持的存储引擎包括InnoDB、MyISAM、MEMORY、CSV、BLACKHOLE、FEDERATED、MRG_MYISAM、ARCHIVE、PERFORMANCE_SCHEMA。其中NDB和InnoDB提供事务安全表,其余存储引擎都是非事务安全表。

各存储引擎的特性

概览

MySQL服务器采用了多层设计和独立模块,插件式存储引擎体系结构,容许将存储引擎加载到正在运新的MySQL服务器中,图中的Pluggable Storage Engines部分。采用MySQL服务器体系结构,因为在存储级别上(也就是Pluggable Storage Engines)提供了一致和简单的应用模型和API,应用程序编程人员和DBA可再也不考虑全部的底层实施细节。所以,尽管不一样的存储引擎具备不一样的能力,应用程序是与之分离的。存储引擎就司职与文件系统打交道了。

各类存储引擎的特性

  1. 并发性:某些应用程序比其余应用程序具备不少的颗粒级锁定要求(如行级锁定)。
  2. 事务支持:并不是全部的应用程序都须要事务,但对的确须要事务的应用程序来讲,有着定义良好的需求,如ACID兼容等。
  3. 引用完整性:经过DDL定义的外键,服务器须要强制保持关联数据库的引用完整性。
  4. 物理存储:它包括各类各样的事项,从表和索引的总的页大小,到存储数据所需的格式,到物理磁盘。
  5. 索引支持:不一样的应用程序倾向于采用不一样的索引策略,每种存储引擎一般有本身的编制索引方法,但某些索引方法(如B-tree索引)对几乎全部的存储引擎来讲是共同的。
  6. 内存高速缓冲:与其余应用程序相比,不一样的应用程序对某些内存高速缓冲策略的响应更好,所以,尽管某些内存高速缓冲对全部存储引擎来讲是共同的(如用于用户链接的高速缓冲,MySQL的高速查询高速缓冲等),其余高速缓冲策略仅当使用特殊的存储引擎时才惟必定义。
  7. 性能帮助:包括针对并行操做的多I/O线程,线程并发性,数据库检查点,成批插入处理等。
  8. 其余目标特性:可能包括对地理空间操做的支持,对特定数据处理操做的安全限制等。

各存储引擎的介绍

InnoDB:MySql 5.6 版本默认的存储引擎。InnoDB 是一个事务安全的存储引擎,它具有提交、回滚以及崩溃恢复的功能以保护用户数据。InnoDB 的行级别锁定以及 Oracle 风格的一致性无锁读提高了它的多用户并发数以及性能。InnoDB 将用户数据存储在汇集索引中以减小基于主键的普通查询所带来的 I/O 开销。为了保证数据的完整性,InnoDB 还支持外键约束。

MyISAM:MyISAM既不支持事务、也不支持外键、其优点是访问速度快,可是表级别的锁定限制了它在读写负载方面的性能,所以它常常应用于只读或者以读为主的数据场景。

Memory:在内存中存储全部数据,应用于对非关键数据由快速查找的场景。Memory类型的表访问数据很是快,由于它的数据是存放在内存中的,而且默认使用HASH索引,可是一旦服务关闭,表中的数据就会丢失

BLACKHOLE:黑洞存储引擎,相似于 Unix 的 /dev/null,Archive 只接收但却并不保存数据。对这种引擎的表的查询经常返回一个空集。这种表能够应用于 DML 语句须要发送到从服务器,但主服务器并不会保留这种数据的备份的主从配置中。

CSV:它的表真的是以逗号分隔的文本文件。CSV 表容许你以 CSV 格式导入导出数据,以相同的读和写的格式和脚本和应用交互数据。因为 CSV 表没有索引,你最好是在普通操做中将数据放在 InnoDB 表里,只有在导入或导出阶段使用一下 CSV 表。

NDB:(又名 NDBCLUSTER)——这种集群数据引擎尤为适合于须要最高程度的正常运行时间和可用性的应用。注意:NDB 存储引擎在标准 MySql 5.6 版本里并不被支持。目前可以支持

MySql 集群的版本有:基于 MySql 5.1 的 MySQL Cluster NDB 7.1;基于 MySql 5.5 的 MySQL Cluster NDB 7.2;基于 MySql 5.6 的 MySQL Cluster NDB 7.3。一样基于 MySql 5.6 的 MySQL Cluster NDB 7.4 目前正处于研发阶段。

Merge:容许 MySql DBA 或开发者将一系列相同的 MyISAM 表进行分组,并把它们做为一个对象进行引用。适用于超大规模数据场景,如数据仓库。

Federated:提供了从多个物理机上联接不一样的 MySql 服务器来建立一个逻辑数据库的能力。适用于分布式或者数据市场的场景。

Example:这种存储引擎用以保存阐明如何开始写新的存储引擎的 MySql 源码的例子。它主要针对于有兴趣的开发人员。这种存储引擎就是一个啥事也不作的 "存根"。你可使用这种引擎建立表,可是你没法向其保存任何数据,也没法从它们检索任何索引。

视图

视图是一个虚拟表(非真实存在),其本质根据SQL语句获取动态的数据集,并为其命名,用户使用时只需使用名称便可获取结果集,能够将该结果集当作表来使用.

使用视图咱们能够把查询过程当中的临时表摘出来,用视图去实现,这样之后再想操做该临时表的数据是就无需重写复杂的SQL了,直接去视图中查找便可,但视图有明显的效率问题,而且视图是放在数据库中的,若是咱们程序中使用的SQL过度依赖数据库中的视图,即强耦合,那就意味着扩展SQL极为不便,所以并不推荐使用

建立视图

create view users_view as select * from users;
select * from users_view;

删除视图

drop view users_view

修改视图

alter view user_view as select * from users where id > 1000;

咱们不可以直接修改视图内是记录,并且在涉及多个表的状况下是根本没法修改视图中的记录的,可是当咱们直接修改表内的记录时,视图中的记录也会发生相应的变化

触发器

触发器是MySQL响应一下任意语句而自动执行的一条MySQL语句(或位于BEGIN和END语句之间的一组语句):

delete

insert

update

其余MySQL语句不支持触发器

建立触发器

在建立触发器时,须要给出4条信息

  • 惟一的触发器名
  • 触发器关联的表
  • 触发器应该响应的活动
  • 触发器什么时候执行

触发器用create trigger语句建立

# 插入前
CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON tb1 FOR EACH ROW
BEGIN
    ...
END

# 插入后
CREATE TRIGGER tri_after_insert_tb1 AFTER INSERT ON tb1 FOR EACH ROW
BEGIN
    ...
END

# 删除前
CREATE TRIGGER tri_before_delete_tb1 BEFORE DELETE ON tb1 FOR EACH ROW
BEGIN
    ...
END

# 删除后
CREATE TRIGGER tri_after_delete_tb1 AFTER DELETE ON tb1 FOR EACH ROW
BEGIN
    ...
END

# 更新前
CREATE TRIGGER tri_before_update_tb1 BEFORE UPDATE ON tb1 FOR EACH ROW
BEGIN
    ...
END

# 更新后
CREATE TRIGGER tri_after_update_tb1 AFTER UPDATE ON tb1 FOR EACH ROW
BEGIN
    ...
END

触发器没法由用户直接调用,而由对表的操做被动引起的

删除触发器

drop trigger newproduct;

存储过程

存储过程包含了一系列可执行的SQL语句,存储过程放于MySQL中,经过调用它的名字能够执行其内部的一堆SQL

存储过程的优势:

  • 用于替代程序写的SQL语句,实现程序与SQL的解耦

  • 基于网络的传输,传别名的数据量小,而直接传sql数据量大

缺点:

  • 程序员扩展功能不方便

建立无参存储过程

delimiter //
create procedure p1()
BEGIN
    select * from blog;
    INSERT into blog(name,sub_time) values("xxx",now());
END //
delimiter ;

#在mysql中调用
call p1() 

#在python中基于pymysql调用
cursor.callproc('p1') 
print(cursor.fetchall())

建立有参存储过程

对于存储过程,能够接收参数,其参数有三种:

in 仅用于传入参数用

out 用于返回值

inout 既能够传入又能够看成返回值

# in:传入参数
delimiter //
create procedure p2(
    in n1 int,
    in n2 int
)
BEGIN
    
    select * from blog where id > n1;
END //
delimiter ;

#在mysql中调用
call p2(3,2)

#在python中基于pymysql调用
cursor.callproc('p2',(3,2))
print(cursor.fetchall())
# out:返回值
delimiter //
create procedure p3(
    in n1 int,
    out res int
)
BEGIN
    select * from blog where id > n1;
    set res = 1;
END //
delimiter ;

#在mysql中调用
set @res=0; #0表明假(执行失败),1表明真(执行成功)
call p3(3,@res);
select @res;

#在python中基于pymysql调用
cursor.callproc('p3',(3,0)) #0至关于set @res=0
print(cursor.fetchall()) #查询select的查询结果

cursor.execute('select @_p3_0,@_p3_1;') #@p3_0表明第一个参数,@p3_1表明第二个参数,即返回值
print(cursor.fetchall())
# inout:既能够传入又能够返回
delimiter //
create procedure p4(
    inout n1 int
)
BEGIN
    select * from blog where id > n1;
    set n1 = 1;
END //
delimiter ;

#在mysql中调用
set @x=3;
call p4(@x);
select @x;


#在python中基于pymysql调用
cursor.callproc('p4',(3,))
print(cursor.fetchall()) #查询select的查询结果

cursor.execute('select @_p4_0;') 
print(cursor.fetchall())

执行存储过程

在MySQL中执行:

-- 无参数
call proc_name()

-- 有参数,全in
call proc_name(1,2)

-- 有参数,有in,out,inout
set @t1=0;
set @t2=3;
call proc_name(1,2,@t1,@t2)

在python中基于pymysql执行:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import pymysql

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='t1')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 执行存储过程
cursor.callproc('p1', args=(1, 22, 3, 4))
# 获取执行完存储的参数
cursor.execute("select @_p1_0,@_p1_1,@_p1_2,@_p1_3")
result = cursor.fetchall()

conn.commit()
cursor.close()
conn.close()


print(result)

删除存储过程

drop procedure proc_name;

SQL函数

MySQL提供了许多内置函数

CHAR_LENGTH(str)
        返回值为字符串str 的长度,长度的单位为字符。一个多字节字符算做一个单字符。
        对于一个包含五个二字节字符集, LENGTH()返回值为 10, 而CHAR_LENGTH()的返回值为5。
    
    CONCAT(str1,str2,...)
        字符串拼接
        若有任何一个参数为NULL ,则返回值为 NULL。
    FORMAT(X,D)
        将数字X 的格式写为'#,###,###.##',以四舍五入的方式保留小数点后 D 位, 并将结果以字符串的形式返回。若 D 为 0, 则返回结果不带有小数点,或不含小数部分。
        例如:
            SELECT FORMAT(12332.1,4); 结果为: '12,332.1000'
    INSTR(str,substr)
        返回字符串 str 中子字符串的第一个出现位置。
    LEFT(str,len)
        返回字符串str 从开始的len位置的子序列字符。
    LOWER(str)
        变小写
    UPPER(str)
        变大写
    LTRIM(str)
        返回字符串 str ,其引导空格字符被删除。
    RTRIM(str)
        返回字符串 str ,结尾空格字符被删去。
    SUBSTRING(str,pos,len)
        获取字符串子序列
    LOCATE(substr,str,pos)
        获取子序列索引位置
    REPEAT(str,count)
        返回一个由重复的字符串str 组成的字符串,字符串str的数目等于count 。
        若 count <= 0,则返回一个空字符串。
        若str 或 count 为 NULL,则返回 NULL 。
    REPLACE(str,from_str,to_str)
        返回字符串str 以及全部被字符串to_str替代的字符串from_str 。
    REVERSE(str)
        返回字符串 str ,顺序和字符顺序相反。
    RIGHT(str,len)
        从字符串str 开始,返回从后边开始len个字符组成的子序列
相关文章
相关标签/搜索