数据库---MySQL(三)

一、视图

视图是一个虚拟表,是sql的查询结果,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据,在使用视图时动态生成。视图的数据变化会影响到基表,基表的数据变化也会影响到视图[insert update delete ]

--创建视图
create view view_name as select * from table_name;
--显示创建视图
show create view view_name;
--显示视图的字段
desc view_name;
--查询视图数据
select * from view_name;
--显示视图
show tables;
--修改视图
alter view view_name as select * from table_name;
--删除视图
drop view view_name;

 

 

 

二、触发器

触发器是与表有关的数据库对象,在满足定义条件时触发,并执行触发器中定义的语句集合。触发器的这种特性可以协助应用在数据库端确保数据的完整性。

--创建触发器
create trigger trigger_name trigger_time trigger_event on table_name for each row
begin
执行语句1;
执行语句2;
end
--删除触发器
drop trigger trigger_name;
  • trigger_time:触发时机,before/after,在trigger_event之前/之后触发
  • trigger_event:触发事件,insert/update/delete,在插入/修改/删除时触发
  • for each row:每一次满足触发器的操作
  • new/old:new指新数据,insert/update会产生新数据;old指老数据,update/delete会产生老数据

 

 

三、函数

MySQL提供许多内置函数,也可以自定义函数;官方内置函数地址https://dev.mysql.com/doc/refman/5.7/en/functions.html

--调用函数
select 函数名(参数);

1.常用内置函数

 函数名称 介绍 示例 
 char_length(str) 返回字符串的长度,单位是字符  select char_length('abcde');返回5    select char_length('中文');返回2
 length(str) 返回字符串的长度,单位是字节 select length('abcde');返回5    select length('中文');返回4
 concat(str1,str2,...) 字符串拼接,返回拼接之后的字符串;若有任何一个参数为null,则返回结果为null select concat_ws('a','','b',null,'c');返回null 
 congcat_ws(separator,str1,str2,...) 字符串拼接,自定义连接符,返回拼接之后的字符串;不会忽略任何的空字符串,但是会忽略null select concat_ws(',','a','','b',null,'c');返回a,,b,c 
 ascii(str)  返回第一个字符的ascii码;如果str是空字符串,返回0。如果str是NULL,返回NULL select ascii('ab');返回97
lower(str)/upper(str) 返回字符串的小写/大写  
 instr(str,substr) 返回子串substr在字符串str中第一次出现的位置;如果字符串中不包含子串,返回0  select instr('foobarbar','bar');返回4   select instr('foobarbar','br');返回0 
 left(str,len)/right(str,len) 返回字符串左边/右边len长度的字符串 select left('qwerty',2);返回qw
 substring(str,pos,len) 返回从pos位置开始的长度为len的字符串;不写len,返回pos位置开始到结尾的字符串 select substring('abcdefg',2,4); 返回bcde
 trim(str)/ltrim(str)/rtrim(str) 返回删除str首尾/首/尾空格的字符串  
replace(str,from_str,to_str) 返回字符串str,其字符串from_str的所有出现由字符串to_str代替 select replace('www.mysql.com','w','ab');返回ababab.mysql.com
repeat(str,count) 返回由重复count次的字符串str组成的一个字符串。如果count <= 0,返回一个空字符串。如果str或count是NULL,返回NULL  
reverse(str) 返回颠倒字符顺序的字符串str  
insert(str,pos,len,newstr) 返回字符串str,在位置pos起始的子串且len个字符长的子串由字符串newstr代替 select insert('abcdefg',3,2,'ooo');返回aboooefg
abs(x) 返回x的绝对值  
mod(m,n)/%: 返回m被n除的余数 select mod(5,2);返回1  select 5%4;返回1
ceiling(x) 返回不小于x的最小整数值 select ceiling(-2.33);返回-2
round(x) 返回参数x的四舍五入的一个整数 select format(12345678.11,4); 返回12,345,678.1100 
format(x,d) 将x保留小数位d位  
now() 返回现在的日期和时间 select now();返回2020-12-15 22:54:12 
curdate() 返回现在的日期  select curdate(); 返回2020-12-15
curtime()  返回现在的时间  select curtime();返回22:54:28  
year(date)/month(date)/day(date) 返回日期的年/月/日 select year(curdate());返回2020 
weekday(date) 返回date的星期索引(0=星期一,1=星期二, ……6= 星期天)  
hour(time)/minute(time)/second(time) 返回时间的时/分/秒  select hour('18:18:18');返回18 
dayofweek(date)/dayofmonth(date)/dayofyear(date)  返回日期date的星期索引(1=星期天,2=星期一, …7=星期六)/返回date的月份中的日期,在1到31范围内/返回date在一年中的日数, 在1到366范围内   
date_format(date,format)  返回格式化时间   select date_format(now(),'%Y-%m %H:%i');返回2020-12 17:14 
if(expr1,expr2,expr3)  如果 expr1 是TRUE (expr1 <> 0 and expr1 <> NULL),则返回值为expr2; 否则返回值则为 expr3。IF() 的返回值为数字值或字符串值,具体情况视其所在语境而定   
ifnull(value1,value2)  如果value1为空,返回value2,否则返回value1  
last_insert_id() 返回最后生成的AUTO_INCREMENT值  
strcmp(str1,str2)  如果字符串相同,STRCMP()返回0,如果第一参数根据当前的排序次序小于第二个,返回-1,否则返回1  
charset(str) 函数返回字符串str的字符集,一般情况这个字符集就是系统的默认字符集 select charset('abc');返回gbk
collatiion(str) 返回字符串str的字符排列方式 select collation('abc');返回gbk_chinese_ci
version(); 返回MySQL的版本  
connection_id() 返回服务器的连接数,也就是到现在为止MySQL服务的连接次数  
database()/schema() 返回当前数据库名  
user()/current_user()/system_user()/session_user() 返回当前用户名  

 2.自定义函数

--自定义函数,自定义函数的函数体内不能包括select语句之类
create function 函数名(参数名 参数类型)  --多个参数之间用,隔开
returns 返回类型  
begin
函数体
end
--删除函数
drop function 函数名;

  • log_bin_trust_function_creators:当二进制日志启用后,这个变量就会启用。它控制是否可以信任存储函数创建者,不会创建写入二进制日志引起不安全事件的存储函数。如果设置为0(默认值),用户不得创建或修改存储函数,除非它们具有除CREATE ROUTINE或ALTER ROUTINE特权之外的SUPER权限。 设置为0还强制使用DETERMINISTIC特性或READS SQL DATA或NO SQL特性声明函数的限制。 如果变量设置为1,MySQL不会对创建存储函数实施这些限制。 此变量也适用于触发器的创建。 

 

四、变量

  •  @变量名:是用户变量
  • @@变量名:是会话变量或全局变量
--设置用户变量
set @变量名 = values;
select @变量名 := values;
--查询变量
show session variables;  --查询所有会话变量
show global variables;  --查询所有全局变量
show variables like '%部分变量名%';   --查询变量
select @变量名--查询用户变量;
select @@session.变量名;  --查询会话变量
select  @@global.变量名;  --查询全局变量
--设置变量
set session 变量名=value;  --设置会话变量
set @@session.变量名=value;   --设置会话变量
set global 变量名=value;   --设置全局变量
set @@global.变量名=value;  --设置全局变量

五、存储过程

存储过程是一个SQL语句集合,当主动去调用存储过程时,其中内部的SQL语句会按照逻辑执行。

--创建存储过程
create procedure 存储过程名称()
begin
SQL语句;
end
--创建有参数的存储过程
create procedure 存储过程名称(
in 参数名称 参数类型,
inout 参数名称 参数类型,
out 参数名称 参数类型)
begin
SQL语句;
end
--调用存储过程
call 存储过程名称(参数);
--删除存储过程
drop procedure 存储过程名称;

1.无参数的存储过程

 

 

2.有参数的存储过程

3.存储过程条件语句

if(条件)
then ...;
elseif(条件)
then ...;
else ...;
end if;

4.存储过程循环语句

4.1while循环

while(条件) do
...;
end while;

4.2 repeat循环

repeat
...;
until 条件
end repeat;

 

 

4.3 loop循环

loopname:loop
...;
if(条件) then
leave loopname;
end if;
end loop;

5.存储过程使用游标

游标是保存查询结果的临时区域

delimiter ||
create procedure p13()
begin
    declare sid int;
    declare sname char(10);
    declare cid int;
    declare flag int default true;
    --cursor和handler变量必须在普通变量的后面
    declare cur cursor for select * from student;
    --游标变量保存了查询的临时结果,就是结果集
    --将游标变量中的结果集都遍历一遍,到达结尾,将flag设为false
    declare continue handler for not found set flag=false;
    open cur;   --打开游标
        fetch cur into sid,sname,cid;  --游标向前走一步,将结果放到变量中
        while(flag) do  --游标还没到达结尾就继续循环
            begin
                insert into t1 values(sid,sname,cid);
                fetch cur into sid,sname,cid;   --每次循环游标向前走一步,当结尾continue为not found设置flag为false,结束循环
            end;
        end while;
    close cur;  --关闭游标
end|| 

 

6.存储过程中的事务

6.1 事务

事务的特征

  • 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。
  • 事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
  • 事务用来管理 insert,update,delete 语句

一般来说,事务是必须满足4个条件(ACID)::原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。

--开启事务
start transaction;
SQL语句;
--提交
commit;
--回滚
rollback;

 

6.2 存储过程中的事务 

delimiter ||
create procedure p15(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 t1;
        delete from t100; --没有t100这个表
        commit;

        --sucess
        set p_return_code=0;
    end||
delimiter ;        

7.动态执行存储过程

8.python执行存储过程 

import pymysql

connect = pymysql.connect("localhost","root","","db1")
cursor = connect.cursor()

# cursor.callproc("p1") #执行没有参数的存储过程
cursor.callproc("p7", args=(1,1,1))   #执行有参数的存储过程
cursor.execute("select @_p7_0,@_p7_1,@_p7_2")   #获取存储过程的第0,1,2个参数,返回元组里套元组
result = cursor.fetchall()
cursor.close()
connect.close()
print(result)

六、索引

索引,是数据库中专门用于帮助用户快速查询数据的一种数据结构。类似于字典中的目录,查找字典内容时可以根据目录查找到数据的存放位置,然后直接获取即可。

索引大大提高了查询速度,但同时会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。建立索引会占用磁盘空间的索引文件。

索引分为普通索引、唯一索引、主键索引、唯一索引

1.普通索引

普通索引的作用,就是加速查找

--创建普通索引
--创建表时,创建索引
create table tablename(
field type ...,
...,
index indexname(field)
);
--表已经存在创建索引
--注意:对于创建索引时如果是BLOB 和 TEXT 类型,必须指定length。
create index indexname on tablename(field([length]))
--修改表结构增加索引
alter table tablename add index indexname(field);
--删除索引
drop index indexname on tablename;
alter table tablename drop index indexname;
--显示索引
show index from table_name;

python造数据

import pymysql
import random

connect = pymysql.connect("localhost","root","","db1")
cursor = connect.cursor()

#如果表已经存在,删除
sql_d = "drop table if exists staff;"
cursor.execute(sql_d)
connect.commit()

#创建staff表
sql_c = """create table staff(
    id int unsigned not null auto_increment primary key,
    name char(10) not null,
    email char(20),
    department_id tinyint unsigned
    )engine=innodb default charset=utf8;"""
cursor.execute(sql_c)
connect.commit()

#插入数据
sql_i = "insert into staff(id,name,email,department_id) values(%s,%s,%s,%s);"
for i in range(1,1000000):  #因为id是unsigned,不能为0
    id = i
    name = "Lucy" + str(i)
    email = name +"@qq.com"
    department_id = random.randint(1,9)
    cursor.execute(sql_i,(id,name,email,department_id))
connect.commit()

cursor.close()
connect.close()

2.唯一索引

--创建唯一索引
--创建表时创建唯一索引
create table tablename(
...,
unique uniquename (field)
);
--表已存在时创建唯一索引
create unique index indexname on tablename(field);
--删除唯一索引
drop index indexname on tablename;

3.组合索引

组合索引是将n个列组合成一个索引,其应用场景为:频繁的同时使用n列来进行查询

--创建组合索引
create index indexname on table(field1,field2);

如创建name和email的组合索引之后,查询:

  • name and email  -- 使用索引
  • name                 -- 使用索引
  • email                 -- 不使用索引

注意:对于同时搜索n个条件时,组合索引的性能好于多个单一索引合并。

4.命中索引

正确使用索引才能加快查询速度,以下方式会降低查询速度

  • 使用like '%...%'
  • 使用函数
  • 使用or ,当or中有未设置索引的列会降低查询速度
  • 类型不一致,如果name的类型是char,但是查询时写name=999,会降低查询速度
  • !=,如果是主键还是会走索引
  • >,如果是主键或者索引是整数类型还是会走索引
  • order by,当排序使用索引,但是映射不是索引时,会降低查询速度,如果是主键还是走索引

5.执行计划

可通过执行计划推测查询语句的时间

explain SQL语句;

 select_type列常见的有:

  • simple:表示不需要union操作或者不包含子查询的简单select查询。有连接查询时,外层的查询为simple,且只有一个
  • primary:一个需要union操作或者含有子查询的select,位于最外层的单位查询的select_type即为primary。且只有一个
  • union:union连接的两个select查询,第一个查询是dervied派生表,除了第一个表外,第二个以后的表select_type都是union
  • dependent union:与union一样,出现在union 或union all语句中,但是这个查询要受到外部查询的影响
  • union result:包含union的结果集,在union和union all语句中,因为它不需要参与查询,所以id字段为null
  • subquery:除了from字句中包含的子查询外,其他地方出现的子查询都可能是subquery
  • dependent subquery:与dependent union类似,表示这个subquery的查询要受到外部表查询的影响
  • derived:from字句中出现的子查询,也叫做派生表,其他数据库中可能叫做内联视图或嵌套select
table:显示的查询表名,如果查询使用了别名,那么这里显示的是别名,如果不涉及对数据表的操作,那么这显示为null,如果显示为尖括号括起来的<derived N>就表示这个是临时表,后边的N就是执行计划中的id,表示结果来自于这个查询产生。
type:依次从好到差:system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,index_subquery,range,index_merge,index,ALL,除了all之外,其他的type都可以使用到索引,除了index_merge之外,其他的type只可以用到一个索引
  • system:表中只有一行数据或者是空表,且只能用于myisam和memory表。如果是Innodb引擎表,type列在这个情况通常都是all或者index
  • const:使用唯一索引或者主键,返回记录一定是1行记录的等值where条件时,通常type是const。其他数据库也叫做唯一索引扫描
  • eq_ref:出现在要连接过个表的查询计划中,驱动表只返回一行数据,且这行数据是第二个表的主键或者唯一索引,且必须为not null,唯一索引和主键是多列时,只有所有的列都用作比较时才会出现eq_ref
  • ref:不像eq_ref那样要求连接顺序,也没有主键和唯一索引的要求,只要使用相等条件检索时就可能出现,常见与辅助索引的等值查找。或者多列主键、唯一索引中,使用第一个列之外的列作为等值查找也会出现,总之,返回数据不唯一的等值查找就可能出现。
  • fulltext:全文索引检索,要注意,全文索引的优先级很高,若全文索引和普通索引同时存在时,mysql不管代价,优先选择使用全文索引
  • ref_or_null:与ref方法类似,只是增加了null值的比较。实际用的不多。
  • unique_subquery:用于where中的in形式子查询,子查询返回不重复值唯一值
  • index_subquery:用于in形式子查询使用到了辅助索引或者in常数列表,子查询可能返回重复值,可以使用索引将子查询去重。
  • range:索引范围扫描,常见于使用>,<,is null,between ,in ,like等运算符的查询中。
  • index_merge:表示查询使用了两个以上的索引,最后取交集或者并集,常见and ,or的条件使用了不同的索引
  • index:索引全表扫描
  • all:全表扫描数据文件
possible_keys:查询可能使用到的索引都会在这里列出来 
key:查询真正使用到的索引
key_len:用于处理查询的索引长度
ref:如果是使用的常数等值查询,这里会显示const,如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段,如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func
rows:这里是执行计划中估算的扫描行数,不是精确值
原文地址:https://www.cnblogs.com/he-202007/p/14141162.html