mysql进阶知识_MySQL进阶知识

本文详细介绍了数据库管理中的关键概念:视图,包括其创建、修改和删除;触发器,用于在数据变化时自动执行的存储过程,确保业务规则和数据完整性;内置与自定义函数,以及如何使用和创建;存储过程,一组SQL语句的集合,用于提升效率;事务处理,确保数据一致性;以及索引的创建和使用策略,强调了正确使用索引以提高查询性能的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

视图

概念:给某个查询语句设置别名,创建这个别名的过程就叫创建视图,这个别名就是视图;注意:视图其实就是给一个select创建别名,在调用的时候才会生效,所以如果源数据内容更改,则视图内容同样会跟着改变

创建格式

create view 视图名称asSQL;

修改视图

alter view 视图名称as新SQL;

删除视图

drop view 视图名称;

例如:

create view v1as select * from student where sid > 10;

触发器

概念:SQL触发器,是一种特殊类型的存储过程,不由用户直接调用。它在指定的表中的数据发生变化时自动生效。唤醒调用触发器以响应 INSERT、UPDATE 或 DELETE 语句。将触发器和触发它的语句作为可在触发器内回滚的单个事务对待。如果检测到严重错误(例如,磁盘空间不足),则整个事务即自动回滚。常常用于强制业务规则和数据完整性。

创建格式

delimiter//# 更改断句符create trigger 触发器名称 BEFORE INSERT on 表名 forEACH ROW

#trigger后面跟触发器名字,表名是告知触发器要在那个表的内容有变动之前做操作,EACH ROW是数据变动一行就触发一次触发器BEGIN

INSERT into teacher(tname) values(NEW.sname);END //# 还原断句符

delimiter ;

创建数据之前触动触发器create table t1(id int auto_increment key,name varchar(10) not null)engine=innodb;create table t2(id int auto_increment key,py varchar(10) not null)engine=innodb;

delimiter \\create trigger tt1 BEFORE INSERT on t1 forEACH ROWBEGIN

insert into t2(py) values(NEW.name);END\\

delimiter ;insert into t1(name) values('梁晓');

创建数据之后触动触发器create table t1(id int auto_increment key,name varchar(10) not null)engine=innodb;create table t2(id int auto_increment key,py varchar(10) not null)engine=innodb;

delimiter \\create trigger tt2 AFTER INSERT on t1 forEACH ROWBEGIN

insert into t2(py) values(NEW.name);END\\

delimiter ;insert into t1(name) values('王文杰');

删除数据之前触动触发器create table t1(id int auto_increment key,name varchar(10) not null)engine=innodb;create table t2(id int auto_increment key,py varchar(10) not null)engine=innodb;

delimiter \\create trigger tt2 BEFORE DELETE on t1 forEACH ROWBEGIN

insert into t2(py) values(NEW.name);END\\

delimiter ;insert into t1(name) values('王文杰');

删除数据之后触动触发器create table t1(id int auto_increment key,name varchar(10) not null)engine=innodb;create table t2(id int auto_increment key,py varchar(10) not null)engine=innodb;

delimiter \\create trigger tt2 AFTER DELETE on t1 forEACH ROWBEGIN

insert into t2(py) values(OLD.name);END\\

delimiter ;insert into t1(name) values('王文杰');

更新数据之前触动触发器create table t1(id int auto_increment key,name varchar(10) not null)engine=innodb;create table t2(id int auto_increment key,py varchar(10) not null)engine=innodb;

delimiter \\create trigger tt2 BEFORE UPDATE on t1 forEACH ROWBEGIN

insert into t2(py) values(NEW.name);END\\

delimiter ;insert into t1(name) values('王文杰');

更新数据之后触动触发器create table t1(id int auto_increment key,name varchar(10) not null)engine=innodb;create table t2(id int auto_increment key,py varchar(10) not null)engine=innodb;

delimiter \\create trigger tt2 AFTER UPDATE on t1 forEACH ROWBEGIN

insert into t2(py) values(OLD.name);END\\

delimiter ;insert into t1(name) values('王文杰');

注意:这里的NEW代表的是新数据,OLD代表的是旧数据

函数

内置函数

mysql中有内置函数,也可以自定义函数,函数用来完成用户的一些特定功能;下面附关于内置函数的教程地址。

https://dev.mysql.com/doc/refman/5.7/en/functions.html(官方地址)

https://www.runoob.com/mysql/mysql-functions.html     (中文教程)

函数的使用格式

select Function();

# Function是函数名,函数名后面可以不跟载体,直接加入参数或者不加

有一个比较要注意的内置date_format,下面附关于这个内置函数的一些相关参数:

%a Abbreviated weekday name (Sun..Sat)%b Abbreviated month name (Jan..Dec)%c Month, numeric (0..12)%D Day of the month with English suffix (0th, 1st, 2nd, 3rd, …)%d Day of the month, numeric (00..31)%e Day of the month, numeric (0..31)%f Microseconds (000000..999999)%H Hour (00..23)%h Hour (01..12)%I Hour (01..12)%i Minutes, numeric (00..59)%j Day of year (001..366)%k Hour (0..23)%l Hour (1..12)%M Month name (January..December)%m Month, numeric (00..12)%p AM or PM%r Time, 12-hour (hh:mm:ss followed by AM or PM)%S Seconds (00..59)%s Seconds (00..59)%T Time, 24-hour (hh:mm:ss)%U Week (00..53), where Sunday is the first day of the week; WEEK() mode 0

%u Week (00..53), where Monday is the first day of the week; WEEK() mode 1

%V Week (01..53), where Sunday is the first day of the week; WEEK() mode 2; used with %X%v Week (01..53), where Monday is the first day of the week; WEEK() mode 3; used with %x%W Weekday name (Sunday..Saturday)%w Day of the week (0=Sunday..6=Saturday)%X Year for the week where Sunday is the first day of the week, numeric, four digits; used with %V%x Year for the week, where Monday is the first day of the week, numeric, four digits; used with %v%Y Year, numeric, four digits%y Year, numeric (two digits)%% A literal %character%x x, for any “x” not listed above

自定义函数

创建自定义函数

delimiter \\

# 更改换行符create functionf1(

#createfunction是固定格式,f1是函数名

i1int,

# i1是参数,int是参数类型

i2int)

# i2是参数,int是参数类型returns int# 设定返回值的数据类型,这个操作叫强定义BEGIN

declare num int;

# 声明一个变量名,并且声明这个变量名的类型set num = i1 +i2;

# 设定函数要操作的具体内容,这里操作具体内容不能用mysql本身有的东西,比如selectreturn(num);

# 返回一个数据END\\

# 结束

delimiter ;

# 还原换行符

删除自定义函数drop function f1;

执行自定义函数select f1(11,22);

# 在查询中执行函数

存储过程

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

存储过程的创建

delimiter//

create procedurep1()

#create procedure是固定格式 p1()是存储过程BEGIN# 设定开始标识select * fromt1;

# 存储过程需要执行的SQL语句END//# 设定结束标识

delimiter ;

call p1()

# 执行p1这个存储过程

存储过程的相关参数in仅用于传入参数用

out 仅用于返回值用

inout 既可以传入又可以当作返回值

所有参数的存储过程实例

delimiter \\create procedurep1(in i1 int,in i2 int,

inout i3int,

out r1int)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;

#@变量名是用来创建mysql会话级的变量

set @t2 = 0;

CALL p1 (1, 2 ,@t1, @t2);SELECT @t1,@t2;

# 这里@变量名也是用来调用会话级的变量

事物

事物用于将某些操作的多个SQL作为原子性操作,一旦有某一个出现错误,即可回滚到原来的状态,从而保证数据库数据完整性。事物需要借助存储过程来进行完成

事物的执行性能并不高

示例

delimiter \\create PROCEDUREp1(

OUT p_return_codetinyint# 定义一个存储过程,并且让这个存储过程返回一个值,以便程序调用

)BEGIN

DECLARE exit handler forsqlexception

# 如果监测到事物执行异常,则执行下面的两个代码BEGIN

--ERROR

set p_return_code = 1;

# 设置p_return_code的返回值是1rollback;

# 事物回滚END;DECLARE exit handler forsqlwarning

# 如果事物执行成功一部分,则执行下面的内容BEGIN

--WARNING

set p_return_code = 2;

# 设置p_return_code的返回值是2rollback;

# 回滚END;

STARTTRANSACTION;

# 开始执行事物DELETE fromtb1;

# 事物内容第一行insert into tb2(name)values('seven');

# 事物内容第二行COMMIT;

# 提交--SUCCESS

set p_return_code = 0;

# 如果上面的事物执行成功,则设置p_return_code的返回值0END\\

delimiter ;

动态执行SQL(防SQL注入)

BEGIN#Routine body goes here.../*SQL语句变量*/

DECLARE vstrSql VARCHAR(3000) DEFAULT '';/*映射表字段*/

DECLARE vSourceTableName VARCHAR(50);DECLARE vSourceIdFieldName VARCHAR(50);DECLARE vSourceNameFieldName VARCHAR(50);DECLARE vTargetTableName VARCHAR(50);DECLARE vTargetIdFieldName VARCHAR(50);DECLARE vTargetNameFieldName VARCHAR(50);/*更新数据*/

DECLARE vnewValue VARCHAR(100);DECLARE vSourceIdFieldValue VARCHAR(100);DECLARE Done INT DEFAULT 0;/*声明游标*/

DECLARE curRow CURSOR FOR

SELECTSourceTableName,SourceIdFieldName,SourceNameFieldName,TargetTableName,TargetIdFieldName,TargetNameFieldNameFROMdb_redundancy.TableFieldMap;/*设置终止标记*/

DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET Done = 1;/*打开游标*/

OPENcurRow;/*循环取出数据*/

FETCH NEXT FROM curRow INTOvSourceTableName,vSourceIdFieldName,vSourceNameFieldName,vTargetTableName,vTargetIdFieldName,vTargetNameFieldName;WHILE Done<>1DO

#获取需要更新的数据SELECT SourceNameFieldNewValue,SourceIdFieldValue INTO vnewValue,vSourceIdFieldValue FROMdb_redundancy.TableFieldValueModifyLogWHERE IsProcess=0 AND SourceTableName=vSourceTableName AND SourceIdFieldName=vSourceIdFieldName AND SourceNameFieldName=vSourceNameFieldNameORDER BY CreateDate DESC limit 1;IF ISNULL(vnewValue) <> NULL || LENGTH(trim(vnewValue))>1 THEN#拼接语句SET vstrSql=CONCAT('UPDATE',vTargetTableName,'SET', vTargetNameFieldName ,'= "',vnewValue,'" WHERE', vTargetIdFieldName ,'=', vSourceIdFieldValue,';');

#注意很重要,将连成成的字符串赋值给一个变量(可以之前没有定义,但要以@开头)SET @vSql=vstrSql;

#预处理需要执行的动态SQL,其中stmt是一个变量PREPARE stmt FROM @vSql;

#执行语句EXECUTEstmt ;

#释放语句DEALLOCATE PREPAREstmt;

#更新历史表中状态标记UPDATE db_redundancy.TableFieldValueModifyLog SET IsProcess=1 WHERE IsProcess=0 AND SourceTableName=vSourceTableName AND SourceIdFieldName=vSourceIdFieldName AND SourceIdFieldValue=vSourceIdFieldValue;END IF;

#重置数据SET vnewValue='';SET vstrSql='';FETCH NEXT FROM curRow INTOvSourceTableName,vSourceIdFieldName,vSourceNameFieldName,vTargetTableName,vTargetIdFieldName,vTargetNameFieldName;END WHILE;/*关闭游标*/

CLOSEcurRow;END

注意:防SQL注入可以在程序级别操作,也可以在SQL语句中做限制

索引

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

索引是一种数据加速查找的结构文件,需要使用者通过相关的SQL语句进行创建

索引概念

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

加速查找及部分约束

功能描述

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

主键索引:加速查找,且内容不能为空、不能重复

普通索引:加速查找

唯一索引:加速查找,且不能重复

组合索引:多列组合成一个索引,功能可以参考上面的索引内容,组合的方式有如下几种

组合主键索引

组合唯一索引

组合普通索引

功能分类

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

hash索引与btree索引,默认使用btree索引

索引种类

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

查询快、插入/更新慢、加速查找需要命中索引内容才可以

索引特点

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

组合索引:特点是最左前缀匹配,组合索引效率大于索引合并

覆盖索引:在索引文件中直接获取数据,这种方式其实也没有多少加速效果

索引合并:把多个单列索引合并使用,特点是方便一个表中有多列需要加速,不足是联合索引速度不如组合索引

名词介绍

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

数据库表中添加索引后确实会让查询速度起飞,但前提必须是正确的使用索引来查询,如果以错误的方式使用,则即使建立索引也会不奏效。即使建立索引,索引也不会生效,索引的命中规则如下:- like '%xx'(尽量不要用like匹配)select * from tb1 where name like '%cn';-使用函数(不要用函数)select * from tb1 where reverse(name) = 'wupeiqi';-orselect * from tb1 where nid = 1 or email = 'seven@live.com';

特别的:当or条件中有未建立索引的列才失效,以下会走索引select * from tb1 where nid = 1 or name = 'seven';select * from tb1 where nid = 1 or email = 'seven@live.com' and name = 'alex'

-类型不一致

如果列是字符串类型,传入条件是必须用引号引起来,不然...select * from tb1 where name = 999;- !=

select * from tb1 where name != 'alex'特别的:如果是主键,则还是会走索引select * from tb1 where nid != 123

- >

select * from tb1 where name > 'alex'特别的:如果是主键或索引是整数类型,则还是会走索引select * from tb1 where nid > 123

select * from tb1 where num > 123

-order byselect email fromtb1 order by name desc;

当根据索引排序时候,选择的映射如果不是索引,则不走索引

特别的:如果对主键排序,则还是走索引:select * fromtb1 order by nid desc;-组合索引最左前缀

如果组合索引为:(name,email)

name and email--使用索引

name--使用索引

email--不使用索引

注意事项:- 避免使用select *

- count(1)或count(列) 代替 count(*)- 创建表时尽量时 char代替 varchar-表的字段顺序固定长度的字段优先-组合索引代替多个单列索引(经常使用多个条件查询时)-尽量使用短索引- 使用连接(JOIN)来代替子查询(Sub-Queries)-连表时注意条件类型需一致- 索引散列值(重复少)不适合建索引,例:性别不适合

索引命中

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

# 作用:加速查询

# 单独创建:create index index_name on table_name(column_name)

# 删除格式:drop index_name on table_name;

# 查看索引:show indexfromtable_name;

# 连表创建:

create table in1(

nidint not nullauto_increment primary key,

name varchar(32) not null,

email varchar(64) not null,

extra text,

index ix_name (name)

)

注意:对于创建索引时如果是BLOB 和 TEXT 类型,必须指定length。

普通索引

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

# 作用:加速查询 和 唯一约束(可含null)

# 单独格式:create unique index 索引名 on 表名(列名)

# 删除格式:drop unique index 索引名 on 表名

# 连表创建:

create table in1(

nidint not nullauto_increment primary key,

name varchar(32) not null,

email varchar(64) not null,

extra text,

unique ix_name (name)

)

唯一索引

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

# 作用:加速查询 和 唯一约束(不可含null)

# 定义格式:alter table 表名 add primary key(列名);

# 删除格式1:alter table 表名 drop primary key;

# 删除格式2:alter table 表名 modify 列名int, drop primary key;

# 创建表+创建主键

create table in1(

nidint not nullauto_increment primary key,

name varchar(32) not null,

email varchar(64) not null,

extra text,

index ix_name (name)

)

或者

create table in1(

nidint not nullauto_increment,

name varchar(32) not null,

email varchar(64) not null,

extra text,

primary key(ni1),

index ix_name (name)

)

主键索引

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

# 作用:将n个列组合成一个索引

# 应用场景:频繁的同时使用n列来进行查询,如:where n1 = 'alex' and n2 = 666。

# 创建表

create table in3(

nidint not nullauto_increment primary key,

name varchar(32) not null,

email varchar(64) not null,

extra text

)

# 创建组合索引

create index ix_name_email on in3(name,email);

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

# 如上创建组合索引之后,查询:

name and email--使用索引

name--使用索引

email-- 不使用索引

组合索引

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值