MYSQL进阶,新手变司机
一、视图
视图是一个虚拟表(非真实存在),其本质是【根据SQL语句获取动态的数据集,并为其命名】,用户使用时只需使用【名称】即可获取结果集,并可以将其当作表来使用。
SELECT
*
FROM
(
SELECT
nid,
NAME
FROM
tb1
WHERE
nid > 2
) AS A
WHERE
A. NAME > 'alex';
临时表搜索
1、创建视图
--格式:CREATE VIEW 视图名称 AS SQL语句
CREATE VIEW v1 AS
SELET nid,
name
FROM
A
WHERE
nid > 4
2、删除视图
--格式:DROP VIEW 视图名称 DROP VIEW v1
3、修改视图
-- 格式:ALTER VIEW 视图名称 AS SQL语句 ALTER VIEW v1 AS
SELET A.nid,
B. NAME
FROM
A
LEFT JOIN B ON A.id = B.nid
LEFT JOIN C ON A.id = C.nid
WHERE
A.id > 2
AND C.nid < 5
4、使用视图
select * from v1
二、触发器
对某个表进行【增/删/改】操作的前后如果希望触发某个特定的行为时,可以使用触发器,触发器用于定制用户对表的行进行【增/删/改】前后的行为。
1、创建基本语法
# 插入前
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
delimiter //
CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON tb1 FOR EACH ROW
BEGIN IF NEW. NAME == 'alex' THEN
INSERT INTO tb2 (NAME)
VALUES
('aa')
END
END//
delimiter ;
插入前触发器
delimiter //
CREATE TRIGGER tri_after_insert_tb1 AFTER INSERT ON tb1 FOR EACH ROW
BEGIN
IF NEW. num = 666 THEN
INSERT INTO tb2 (NAME)
VALUES
(''),
('') ;
ELSEIF NEW. num = 555 THEN
INSERT INTO tb2 (NAME)
VALUES
(''),
('') ;
END IF;
END//
delimiter ;
后触发器
特别的:NEW表示即将插入的数据行,OLD表示即将删除的数据行。
2、删除触发器
DROP TRIGGER tri_after_insert_tb1;
3、使用触发器
触发器无法由用户直接调用,而是由于对表的【增/删/改】操作被动引发的。
insert into tb1(num) values(666)
三、存储过程
存储过程是一个SQL语句集合,当主动去调用存储过程时,其中内部的SQL语句会按照逻辑执行。
1、创建存储过程
-- 创建存储过程 delimiter //
create procedure p1()
BEGIN
select * from t1;
END//
delimiter ; -- 执行存储过程 call p1()
对于存储过程,可以接收参数,其参数有三类:
- in 仅用于传入参数用
- out 仅用于返回值用
- inout 既可以传入又可以当作返回值
-- 创建存储过程
delimiter \\
create procedure p1(
in i1 int,
in i2 int,
inout i3 int,
out r1 int
)
BEGIN
DECLARE temp1 int;
DECLARE temp2 int default 0; set temp1 = 1; set r1 = i1 + i2 + temp1 + temp2; set i3 = i3 + 100; end\\
delimiter ; -- 执行存储过程
set @t1 =4;
set @t2 = 0;
CALL p1 (1, 2 ,@t1, @t2);
SELECT @t1,@t2;
有参存储过程
2、删除存储过程
drop procedure proc_name;
3、执行存储过程
-- 无参数
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)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import pymysql conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', 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)
pysql执行存储过程
四、事务
事务用于将某些操作的多个SQL作为原子性操作,一旦有某一个出现错误,即可回滚到原来的状态,从而保证数据库数据完整性。
delimiter \\
create PROCEDURE p1(
OUT p_return_code tinyint
)
BEGIN
DECLARE exit handler for sqlexception
BEGIN
-- ERROR
set p_return_code = 1;
rollback;
END; DECLARE exit handler for sqlwarning
BEGIN
-- WARNING
set p_return_code = 2;
rollback;
END; START TRANSACTION;
DELETE from tb1;
insert into tb2(name)values('seven');
COMMIT; -- SUCCESS
set p_return_code = 0; END\\
delimiter ;
set @i =0;
call p1(@i);
select @i;
支持事务的存储过程
五、索引
索引,是数据库中专门用于帮助用户快速查询数据的一种数据结构。类似于字典中的目录,查找字典内容时可以根据目录查找到数据的存放位置,然后直接获取即可。
30 10 40 5 15 35 66 1 6 11 19 21 39 55 100
MySQL中常见索引有:
- 普通索引
- 唯一索引
- 主键索引
- 组合索引
1、普通索引
普通索引仅有一个功能:加速查询
create table in1(
nid int not null auto_increment primary key,
name varchar(32) not null,
email varchar(64) not null,
extra text,
index ix_name (name)
)
创建表和索引
create index index_name on table_name(column_name)
创建索引
drop index_name on table_name;
删除索引
show index from table_name;
查看索引
注意:对于创建索引时如果是BLOB 和 TEXT 类型,必须指定length。
create index ix_extra on in1(extra(32));
2、唯一索引
唯一索引有两个功能:加速查询 和 唯一约束(可含null)
create table in1(
nid int not null auto_increment primary key,
name varchar(32) not null,
email varchar(64) not null,
extra text,
unique ix_name (name)
表+唯一索引
create unique index 索引名 on 表名(列名)
创建唯一索引
drop unique index 索引名 on 表名
删除唯一索引
3、主键索引
主键有两个功能:加速查询 和 唯一约束(不可含null)
create table in1(
nid int not null auto_increment primary key,
name varchar(32) not null,
email varchar(64) not null,
extra text,
index ix_name (name)
) OR create table in1(
nid int not null auto_increment,
name varchar(32) not null,
email varchar(64) not null,
extra text,
primary key(ni1),
index ix_name (name)
)
创建主键和主键索引
alter table 表名 add primary key(列名);
创建主键
alter table 表名 drop primary key;
alter table 表名 modify 列名 int, drop primary key;
删除主键
4、组合索引
组合索引是将n个列组合成一个索引
其应用场景为:频繁的同时使用n列来进行查询,如:where n1 = 'alex' and n2 = 666。
create table in3(
nid int not null auto_increment primary key,
name varchar(32) not null,
email varchar(64) not null,
extra text
)
创建表
create index ix_name_email on in3(name,email);
创建组合索引
如上创建组合索引之后,查询:
- name and email -- 使用索引
- name -- 使用索引
- email -- 不使用索引
注意:对于同时搜索n个条件时,组合索引的性能好于多个单一索引合并。
5、索引的相关命令和注意事项
# 查看索引
show index from 表名 # 查看执行时间
set profiling = 1; # 开启profiling
SQL... # 执行SQL语句
show profiles; # 查看结果 # 避免使用select *
# count(1)或count(列) 代替 count(*)
# 创建表时尽量时 char 代替 varchar
# 表的字段顺序固定长度的字段优先
# 组合索引代替多个单列索引(经常使用多个条件查询时)
# 尽量使用短索引
# 使用连接(JOIN)来代替子查询(Sub-Queries)
# 连表时注意条件类型需一致
# 索引散列值(重复少)不适合建索引,例:性别不适合
6、正确使用索引
# like '%xx',避免%_写在开头
select * from tb1 where name like '%n'; # 使用函数
select * from tb1 where reverse(name) = 'nick'; # or
select * from tb1 where nid = 1 or email = '630571017@qq.com';
注:当or条件中有未建立索引的列才失效,否则会走索引 # 类型不一致
如果列是字符串类型,传入条件是必须用引号引起来。
select * from tb1 where name = 999; # !=,不等于
select * from tb1 where name != 'nick'
注:如果是主键,则还是会走索引
select * from tb1 where nid != 123 # >,大于
select * from tb1 where name > 'nick'
注:如果是主键或索引是整数类型,则还是会走索引
select * from tb1 where nid > 123
select * from tb1 where num > 123 # order by
select email from tb1 order by name desc;
当根据索引排序时候,选择的映射如果不是索引,则不走索引
注:如果对主键排序,则还是走索引:
select * from tb1 order by nid desc; # 组合索引最左前缀
如果组合索引为:(name,email),查询使用:
name and email -- 使用索引
name -- 使用索引
email -- 不使用索引
六、其他
delimiter \\
CREATE PROCEDURE proc_if ()
BEGIN declare i int default 0;
if i = 1 THEN
SELECT 1;
ELSEIF i = 2 THEN
SELECT 2;
ELSE
SELECT 7;
END IF; END\\
delimiter ;
if语句
delimiter \\
CREATE PROCEDURE proc_while ()
BEGIN DECLARE num INT ;
SET num = 0 ;
WHILE num < 10 DO
SELECT
num ;
SET num = num + 1 ;
END WHILE ; END\\
delimiter ;
while循环
delimiter \\
CREATE PROCEDURE proc_repeat ()
BEGIN DECLARE i INT ;
SET i = 0 ;
repeat
select i;
set i = i + 1;
until i >= 5
end repeat; END\\
delimiter ;
repeat循环
delimiter \\
CREATE PROCEDURE proc_loop ()
BEGIN declare i int default 0;
loop_label: loop
select i;
set i=i+1;
if i>=5 then
leave loop_label;
end if;
end loop; END\\
delimiter ;
loop
delimiter \\
DROP PROCEDURE IF EXISTS proc_sql \\
CREATE PROCEDURE proc_sql ()
BEGIN
declare p1 int;
set p1 = 11;
set @p1 = p1; PREPARE prod FROM 'select * from tb2 where nid > ?';
EXECUTE prod USING @p1;
DEALLOCATE prepare prod; END\\
delimiter ;
动态执行mysql
七、执行计划
mysql> explain select * from suoning;
+----+-------------+---------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | suoning | ALL | NULL | NULL | NULL | NULL | 4 | |
+----+-------------+---------+------+---------------+------+---------+------+------+-------+
1 row in set (1.67 sec) id
查询顺序标识
如:mysql> explain select * from (select nid,name from tb1 where nid < 10) as B;
+----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 9 | NULL |
| 2 | DERIVED | tb1 | range | PRIMARY | PRIMARY | 8 | NULL | 9 | Using where |
+----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
特别的:如果使用union连接气值可能为null select_type
查询类型
SIMPLE 简单查询
PRIMARY 最外层查询
SUBQUERY 映射为子查询
DERIVED 子查询
UNION 联合
UNION RESULT 使用联合的结果
...
table
正在访问的表名 type
查询时的访问方式,性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const
ALL 全表扫描,对于数据表从头到尾找一遍
select * from tb1;
特别的:如果有limit限制,则找到之后就不在继续向下扫描
select * from tb1 where email = 'seven@live.com'
select * from tb1 where email = 'seven@live.com' limit 1;
虽然上述两个语句都会进行全表扫描,第二句使用了limit,则找到一个后就不再继续扫描。 INDEX 全索引扫描,对索引从头到尾找一遍
select nid from tb1; RANGE 对索引列进行范围查找
select * from tb1 where name < 'alex';
PS:
between and
in
> >= < <= 操作
注意:!= 和 > 符号 INDEX_MERGE 合并索引,使用多个单列索引搜索
select * from tb1 where name = 'alex' or nid in (11,22,33); REF 根据索引查找一个或多个值
select * from tb1 where name = 'seven'; EQ_REF 连接时使用primary key 或 unique类型
select tb2.nid,tb1.name from tb2 left join tb1 on tb2.nid = tb1.nid; CONST 常量
表最多有一个匹配行,因为仅有一行,在这行的列值可被优化器剩余部分认为是常数,const表很快,因为它们只读取一次。
select nid from tb1 where nid = 2 ; SYSTEM 系统
表仅有一行(=系统表)。这是const联接类型的一个特例。
select * from (select nid from tb1 where nid = 1) as A;
possible_keys
可能使用的索引 key
真实使用的 key_len
MySQL中使用索引字节长度 rows
mysql估计为了找到所需的行而要读取的行数 ------ 只是预估值 extra
该列包含MySQL解决查询的详细信息
“Using index”
此值表示mysql将使用覆盖索引,以避免访问表。不要把覆盖索引和index访问类型弄混了。
“Using where”
这意味着mysql服务器将在存储引擎检索行后再进行过滤,许多where条件里涉及索引中的列,当(并且如果)它读取索引时,就能被存储引擎检验,因此不是所有带where子句的查询都会显示“Using where”。有时“Using where”的出现就是一个暗示:查询可受益于不同的索引。
“Using temporary”
这意味着mysql在对查询结果排序时会使用一个临时表。
“Using filesort”
这意味着mysql会对结果使用一个外部索引排序,而不是按索引次序从表里读取行。mysql有两种文件排序算法,这两种排序方式都可以在内存或者磁盘上完成,explain不会告诉你mysql将使用哪一种文件排序,也不会告诉你排序会在内存里还是磁盘上完成。
“Range checked for each record(index map: N)”
这个意味着没有好用的索引,新的索引将在联接的每一行上重新估算,N是显示在possible_keys列中索引的位图,并且是冗余的。
MYSQL进阶,新手变司机的更多相关文章
- 【转】MySQL— 进阶
[转]MySQL— 进阶 目录 一.视图 二.触发器 三.函数 四.存储过程 五.事务 一.视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需 ...
- MySQL进阶篇(03):合理的使用索引结构和查询
本文源码:GitHub·点这里 || GitEE·点这里 一.高性能索引 1.查询性能问题 在MySQL使用的过程中,所谓的性能问题,在大部分的场景下都是指查询的性能,导致查询缓慢的根本原因是数据量的 ...
- (6)MySQL进阶篇SQL优化(MyISAM表锁)
1.MySQL锁概述 锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算资源 (如 CPU.RAM.I/O 等)的抢占以外,数据也是一种供许多用户共享的资源.如何保证数 据并 ...
- mysql进阶(二十九)常用函数
mysql进阶(二十九)常用函数 一.数学函数 ABS(x) 返回x的绝对值 BIN(x) 返回x的二进制(OCT返回八进制,HEX返回十六进制) CEILING(x) 返回大于x的最小整数值 EXP ...
- mysql进阶(二十八)MySQL GRANT REVOKE用法
mysql进阶(二十八)MySQL GRANT REVOKE用法 MySQL的权限系统围绕着两个概念: 认证->确定用户是否允许连接数据库服务器: 授权->确定用户是否拥有足够的权限执 ...
- mysql进阶(二十七)数据库索引原理
mysql进阶(二十七)数据库索引原理 前言 本文主要是阐述MySQL索引机制,主要是说明存储引擎Innodb. 第一部分主要从数据结构及算法理论层面讨论MySQL数据库索引的数理基础. ...
- mysql进阶(二十六)MySQL 索引类型(初学者必看)
mysql进阶(二十六)MySQL 索引类型(初学者必看) 索引是快速搜索的关键.MySQL 索引的建立对于 MySQL 的高效运行是很重要的.下面介绍几种常见的 MySQL 索引类型. 在数 ...
- mysql进阶(十六)常见问题汇总
mysql进阶(十六)常见问题汇总 MySQL视图学习: http://www.itokit.com/2011/0908/67848.html 执行删除操作时,出现如下错误提示: 出现以上问题的原因是 ...
- MySQL进阶(视图)---py全栈
目录 mysql进阶(视图)---py全栈 一.什么是视图? 二.视图的特性 三.视图的优点 四.使用场合 五.视图基本操作 六.案例 mysql进阶(视图)---py全栈 一.什么是视图? 视图是从 ...
随机推荐
- Uiautomator 2.0之UiObject2类学习小记
1. 基础动作 1.1. 相关API介绍 API 说明 clear() 清楚编辑框内的内容 click() 点击一个对象 clickAndWait(EventCondition<R> co ...
- 关于laravel 5.3 使用redis缓存出现 找不到Class 'Predis\Client' not found的问题
昨天使用5.3.版本的laravel框架开发公司新项目, 发现将cache和session设置为了redis,执行了一下首页访问. 如图: laravel 版本号 简单配置一下控制器路由, Route ...
- cronolog分割Tomcat catalina.out日志
Linux上tomcat的日志输出在catalina.out里面,随着时间的推移,产生的日志文件会越来越大,其主要是调试中打印的一些信息占空间,比如说System.out和log等等.tomcat 的 ...
- Use Qt in Debian for OpenCASCADE
Use Qt in Debian for OpenCASCADE eryar@163.com Recently several OpenCASCADE enthusiasts want to buil ...
- SQL 联合查询 + XML解析
(select a.EBILLNO, a.EMPNAME, a.APPLYDATE, b.HS_NAME, ), ),'') as SUMMARY, cast(c.XmlData as XML).va ...
- 使H1 H2等标签不换行
在网页优化中,经常要使用H标签对关键字进行优化, 可是如果是一行文字中的某个词加上了H1标记,就会换行. 可以使用下面的方法,H标签就不会强制换行了. <style type="tex ...
- [ASP.NET] 如果将缓存“滑动过期时间”设置为1秒会怎样?
今天编写了一个采用ASP.NET Caching的组件,在为它编写Unit Test的过程中发现了一个有趣的问题,接下来我通过一个简单的实例说明这个问题.我们在一个控制台应用中编写了如下一段程序,这个 ...
- ASP.NET WebAPi(selfhost)之文件同步或异步上传
前言 前面我们讲过利用AngularJs上传到WebAPi中进行处理,同时我们在MVC系列中讲过文件上传,本文结合MVC+WebAPi来进行文件的同步或者异步上传,顺便回顾下css和js,MVC作为客 ...
- MyCAT实现MySQL的读写分离
在MySQL中间件出现之前,对于MySQL主从集群,如果要实现其读写分离,一般是在程序端实现,这样就带来一个问题,即数据库和程序的耦合度太高,如果我数据库的地址发生改变了,那么我程序端也要进行相应的修 ...
- IDDD 实现领域驱动设计-一个简单的 CQRS 示例
上一篇:<IDDD 实现领域驱动设计-CQRS(命令查询职责分离)和 EDA(事件驱动架构)> 学习架构知识,需要有一些功底和经验,要不然你会和我一样吃力,CQRS.EDA.ES.Saga ...