0 视图
0.1 视图定义
视图是有查询结果形成的一张虚拟表,是表通过某种运算得到的一个投影。
同一张表可以创建多个视图
创建视图语法:
create view 视图名称 as select 语句
说明:
- 视图名跟表名是一个级别的名字,隶属于数据库;
- 该语句的含义可以理解为:就是将该select命名为该名字(视图名)
- 该视图也可以设定自己的字段名,而不是select语句本身的字段名(通常不设置)
- 视图的使用几乎和表一样(只不过一般都用做查询,很少增删改,增删改在后面说明)
0.2 视图的作用
- 可以简化查询
案例:1.查询平均价格前3的栏目
以前的SQL语句1
select cat_id,avg(shop_price) as pj from ecs_goods group by cat_id order by pj limit 3;
应用视图的
1) 创建一个视图1
create view ecs_goods_v1 as select cat_id,avg(shop_price) as pj from ecs_goods group by cat_id;
2) 查询平均价格前3只需要查询视图即可1
selcet * from ecs_goods_v1 order by pj desc limit 3;
案例:2.查询出商品表,以及所在的栏目名称
以前的sql语句1
2select goods_id,goods_name,b.cat_name,shop_price from ecs_goods a
left join ecs_category b on a.vat_id=b.cat_id
1) 创建视图1
2
3create view ecs_goods_v2 as
select goods_id,goods_name,b.cat_name,shop_price from ecs_goods a
left join ecs_category b on a.vat_id=b.cat_id
2) 查询视图1
selcet * from ecs_goods_v2;
- 可以进行权限控制
把表的权限封闭,但是开放相应的视图权限,视图里只开放部分数据,比如用户表为例,两个网站搞合作,可以查询对方网站的用户,需要向对方开放用户表的权限,但是又不想开放用户表中的密码字段。
再比如一个goods表,两个网站搞合作,可以互相查询对方的商品列表,比如进货价格字段不能让对方看到
案例
1) 创建一个视图,视图中不能包含进价字段(in_price)1
creat view goods_v1 as select id,goods_name,shop_price from goods;
2) 创建一个用户,授予查询权限,只能操作goods_v1表(视图)1
grant select on php.goods_v1 to 'xiaoming'@'%' identified by '123456';
3) 这样就把新建的用户给合作方
0.3 视图操作
- 查询视图
语法:
select * from 视图名 [where 条件]
视图和表一样,可以添加where条件
- 修改视图
alter view 视图名称 as select ….
- 删除视图
drop view 视图名称
- 查看视图结构
和表一样,语法:
desc 视图名称
- 查看所有视图
和表一样,语法:
show tables;
注意:没有show views 语句
视图和表得关系
表 >>——>> 视图
表改变了视图就改变了
视图 >>——>> 表
修改:
1) 如果没有计算的来的值(avg),视图改变可以影响表
增加:
2) 如果没有不能为空而又刚好没被视图收录的字段,视图创建可以影响创建视图算法
algorithm = merge/temptable/undefined
名称 | 算法 | 创建方式 |
---|---|---|
merge | 当引用视图时,引用视图的语句与定义视图的语句合并(默认) | 意味着视图只是一个语句规则,当查询视图时,吧查询视图的语句与创建时语句where子句等合并,分析,形成一条select语句 |
temptable | 当引用视图时,根据视图语句创建一张临时表 | 根据创建语句,瞬间创建一张临时表,然后查询视图的语句,从该临时表查询数据 |
undefined | 未定义,让系统自动选择 |
1 SQL编程
1.1 声明变量
- 会话变量
定义形式set @变量名 = 值;
说明:
1) 和js类似,第一次给其赋值,就算定义了
2) 它可以在变成环境和非编程环境中使用
3) 使用的任何场合都该带“@”符号
- 普通变量
定义形式:declare 变量名 类型 【default 默认值】;
说明:
1) 他必须先声明(即定义),此时也可以赋值;
2) 赋值跟会话变量一样set 变量名 = 值;
3) 它只能在编程环境中使用
!!!
(编程环境指的是:存储过程,函数,触发器)
- 变量赋值形式
1) 语法1:set 变量名 = 表达式;
此语法中的变量必须先使用declare声明
2) 语法2:
set @变量名 = 表达式
此方式可以无需declare语法声明,而是直接赋值,类似js定义变量并赋值;
3) 语法3:
select @变量名:= 表达式;
此语句会给变量赋值,同时还会作为一个select语句输出结果
4) 语法4:
select 表达式 into @变量名;
此语句虽然看起来是select语句,但是其实并不输出结果集,而是给变量赋值
1.2运算符
- 算术运算符
+,-,*,/,%
注意musql没有++和--
- 关系运算符
< <= = <> !=
- 逻辑运算符
and or not
1.3语句包含模块
所谓语句包含符,在js中,以及大部分其他语言中,大都是{}
它用在很多场合if,switch,for,function
而mysql编程包含的语句符是:
begin【什么】 end【什么】
1.4条件判断
MySQL支持两种判断if判断和case判断
- if
单分支语法:
if 条件 then
//代码
end if;
双分支
if 条件 then
//代码1
else
//代码2
end if;
多分枝
if 条件 then
//代码1
elseif 条件 then
//代码2
else
//代码3
end if;
注意:通常情况下;表示sql的结束,同时向服务器提交并执行,但存储过程中很多SQL语句每一句都是;分开的,这时候我们就需要用其他符号来代替向服务器提交的命令
delimiter 符号
案例:接收4个数字,如果输入1=春天,2=夏天,3=秋天,4=冬天,其他=出错
先修改;符号
delimiter $
1 | create procedure p1 (n int) |
- case判断
case 变量
when 值 then 语句;
when 值 then 语句;
else 语句;
end case;
上面的例子我们改变如下
1 | create procedure p2 (n int) |
1.5循环
Mysql支持的循环有loop,while,repeat循环
- loop循环
标签名:loop
leave 标签名(退出循环)
end loop;
案例:循环1到n的和
1 | create procedure p3 (n int) |
- while循环
标签名 while 条件 do
// 代码
end while
1 | create procedure p4 (n int) |
- repeat循环
repeat
// 代码
until 条件 end repeat;
1 | create procedure p5 (n int) |
2 存储过程
存储过程是在大型数据库系统中,一组为了完成特定功能的SQL语句集,存储在数据库中,经过第一次编译后再次调用不需要再次编译,用户通过制定存储过程的名字,并给出参数(如果该存储过程携带参数)来执行。
存储过程是数据库中的一个重要对象,任何一个设计良好的数据库应用程序都应该用到存储过程。
2.1 好处
存储过程只是在创建时进行编译,以后每次执行存储过程不需要再重新编译,而一般SQL语句每执行一次就编译一次,所以使用存储过程可以提高数据库执行速度。
当对数据库进行复杂操作时(如对多个表进行增删改时),可以将此复杂操作用存储过程封装起来,与数据库提供的事务结合一起使用
存储过程可以重复使用,减少数据库开发人员的工作量
安全性提高,可设定只有某些用户才具有对指定的存储过程使用权限
2.2 存储过程操作
- 创建存储过程
1 | create procedure 存储过程名称(参数1,参数2,...) |
存储过程的参数部分为输入参数(in),输出参数(out),输入输出参数(inout),默认是输入参数。
如果存储过程中就一条语句,begin和end是可以省略的。
说明:
1) 存储过程中,可有各种变成元素:(变量,流程控制,函数调用);
2) 还可以有:增删改查等各种sql语句
3) 其中select(或show,或desc)会作为存储过程执行后的“结果集”返回;
4)形参可以设定数据的“进出方向”
案例1:查询一个表里面某些语句
1 | create procedure p10() |
案例2:输入一个字符串,如果是h输出价格大于1000商品,其他输出小于1000商品
1 | create procedure p11(str char(1)) |
- 调用存储过程
语法:
call 存储过程()
- 删除存过程
语法:
drop procedure [if exists] 存储过程名
- 创建复杂存储过程
案例1:带输出参数的存储过程
1 | create procedure p12(in n int,out res int) |
案例2:带有输入输出参数的存储过程1
2
3
4
5
6create procedure p13(inout n int)
begin
set n = n*n;
end;
set @a = 20; call p13(@a);select @a;
2.3 变量
- 系统变量
MySQL启动的时候就存在的变量,以@@开头的都是系统变量
查询mysql版本:
select @@version;
- 用户变量
用户变量只要在前面加一个@就可以1
2set @name='linjiad';
select @name;
3 函数
和js中的函数几乎一样:需要先定义,然后调用。只是规定这个函数必须需要一个返回值;
3.1 定义函数
语法:
1 | create function 函数名(参数) |
说明:
1) 函数内部可以有各种编程语言元素:变量,流程控制,函数调用;
2) 函数内部可以有增删改等语句
3)但:函数内部不可以有查(select或show,或desc)这种返回结果集的语句
3.2 调用
跟系统函数调用一样:任何需要数据的位置,都可以调用该函数
案例1:返回两个数的和1
2
3
4
5
6create function he(num1 int,num2 int) return int
begin
return num1+num2;
end;
select he(100,120);
案例2: 返回1到n的和1
2
3
4
5
6
7
8
9
10
11
12create function hee(n int) return int
begin
declare i int default 1;
declare s int default 0;
while i <=n do
set s= s + i;
set i= i + 1;
end while;
retuen s;
end;
select he(100,120);
注意:创建的函数是属于数据库的,只能在创建函数的数据库中才能使用;
3.3 SQL内部函数
- 数字类
1) select rand(); //返回0到1之间的随机数
2) select * from it_goods //随机取出两个商品
3) select floor(3.9) // 向上取整 4
4) select ceil(3.1) // 向下取整 3
5) select round(3.5) // 四舍五入 4
- 大小写转换
1) select ucase(‘linjiad’) //转换成大写
2) select icase(‘linjiad’)//转换成小写
- 字符串截取
1) select left(‘abcde’,3) //从左边截取
2) select right(‘abcde’,3) //从右边截取
3) select substring(‘abcde’,2,3) //从第二个位置开始,截取3个
4) select concat(‘abc’,’:de’) //字符串项链 10:abcde
5) coalesce(str1,str2) //返回参数中的第一个非空表达式
select stuname.stusex,coalesce(writtenexam,’缺考’),coalesce(labexam,’缺考’) from stuinfo
6) select length(‘锄禾日当午’) //显示字节个数 10
7) select char_length(‘锄禾日当午’) //显示字符个数 5
8) select length(trim(‘ abc ‘)) //trim 用来去除字符串两边空格
9) select replace(‘abc’,’bc’,’pache’) //将bc替换成pache
- 时间类
1) select unix_timestamp() // 时间戳
2) select from unixtime(unix_timestamp()) //将时间戳转换成日期格式
select from_unixtime(unix_timestamp(),’%Y-%m-%d’);
3) curdate (); //返回今天得日期
select curdate(); // 2018-12-07
4) select now();// 去除当前时间
select now();// 2018-12-07 15:02:59
5) select year(now()) 年, mouth(now()) 月,day(now()) 天,hour(now()) 小时。minute(now()) 分,second(now()) 秒
6) select datediff(now(),’1997-7-1’)// 两个日期相聚多少天
7) if(表达式,值1,值2) //类似三元云算法
select concat(10,if(10%2=0,’偶数’,’奇数’))
8) date_sub 和date_add //时间加减
date_sub(时间日期时间,interval 数字 时间单位)
①:时间单位:可以是year month day hour minute second
②数字:可以是正数和负数(具体看案例2)
- 案例
案例1: 查询今天得电影
①curdate()求出今天的日期
②把添加的时间戳,转换成日期
select title from dede_archives where curdate()=from_unixtime(senddate,’%Y-%m-%d’);
案例2: 求昨天添加的电影
① 去除昨天日期
select date_sub(curdate(),interval 1 day)
或者
select date_add(curdate(),interval -1 day)
4 触发器
4.1 简介
- 触发器是一个特殊的存储过程,它是Mysql在insert,update,delete的时候自动执行的代码块。
- 触发器必须定义在特定表上
- 自动执行,不能直接调用
作用:监视某种情况并触发某种操作
触发器的思路:
监视X表,如果X表里面有增删改的操作,则自动触发Y里面增删改操作。
比如用户表增加新用户,相应的订单表增加该用户的信息。
目前mysql不支持多个具有同一个动作,同一时间,同一事件,同一地点,的触发器。
4.2 创建触发器
- 监视地点(table)
- 监视事件(insert/update/delete)
- 触发时间(after/before)
- 触发事件(insert/update/delete)
语法:
1 | create trigger 触发器名 |
4.3 案例
- 案例1:第一个触发器,购买一个订单表减少一个
1) 监视地点 it_order表
2) 监视事件 it_order表的inset操作
3) 触发时间 it_order表的inset之后
4) 触发事件 it_goods表减少库存的操作
1 | create trigger t1 |
这个t1是有问题的,我们购买任何商品都是减少id=2的对应库存
案例2: 购买商品,减少对应库存
如何在触发器中引用行的值?
对于insert而言,新增的行用new来表示,行中的每一列的值,用new.列名来表示。1
2
3
4
5
6create trigger t1
after inster on it_order
for each row
begin
update it_goods set goods_number=goods_number - new.much where id = new.goods_id;
end案例3:取消订单时,减掉的库存要添加回来
删除行我们用old来表示,如果要引用里面的数据,则使用old.列名来表示
1) 监视地点 it_order表
2) 监视事件 it_order表的delete操作
3) 触发时间 it_order表的delete之后
4) 触发事件 it_goods表减少库存恢复过来
1 | create trigger t3 |
- 案例4:修改订单时,库存也要做对应修改(可以修改购买数量,也可以修改类型)
如果是修改操作要引用it_order里面的值
修改前的数据用old表示,old.列名引用被修改之前的值
修改后的数据用new表示,new.列名引用被修改之后的值
1) 监视地点 it_order表
2) 监视事件 it_order表的update操作
3) 触发时间 it_order表的update之后
4) 触发事件 it_goods表要修改对应的库存
1 | create trigger t4 |
4.4 其他操作
- 删除触发器
drop trigger 触发器名称
- 查看触发器
show triggers
4.5 befor和after
after是先完成数据的增删改,再出发,触发器中的语句晚于监视的增删改,无法影响前面的增删改动作
类似于自助餐,先付钱,在吃饭,无法影响吃多少
befor是先完成出发,再增删改,触发的语句先于监视的增删改发生,我们有机会判断修改即将发生的操作
案例:对于已下的订单,进行判断,如果订单数量>5,就认为是恶意订单,强制吧所定的商品数量改成5
1) 监视地点 it_order表
2) 监视事件 it_order表的insert操作
3) 触发时间 it_order表的insert之前
4) 触发事件 如果购买数量>5就把购买数量改成5
1 | create trigger t5 |
最后更新: 2018年12月08日 10:46