MySQL视图和存储过程详解

一 mysql视图
1 视图的目的:
让同一个数据库被访问时,对于不同的登录帐号,显示不同的数据信息

2 视图的优点:
1)数据独立: 一旦视图结构确定,可以屏蔽表结构对用户的影响
2)安全: 用户只能看到视图中的数据
3)简单: 用户不需要关心视图中的数据如何查询获得,视图中的数据已经是经过筛选好的符合条件的结果集

3 视图使用的限制:
不能在视图上创建索引
在视图的FROM子句中不使用子查询

4 视图的使用:
1)创建一个视图:

create view v1 as select * from user;
create view v2(vname,vgid) as select user,uid from user;

如果在视图表中不定义字段名,那么默认为基表的字段名
如果需要定义字段名。字段数量需要与基表一样。

2)查看所有表状态

mysql> show table status\G;

Comment: VIEW
comment字段的值为view的为视图
comment字段值为空时为基表

3)显示创建视图v1的命令:

mysql> show create view v1\G;
mysql> show table status where comment="VIEW"\G;

在正常情况下,修改基表里的数据,视图里的数据会跟着改变
修改视图里的数据,基表里的数据也会改变
当创建基表的时候如果有指定条件,那么在修改数据时,只要符合条件的数据都会在
视图中显示,不符合条件的不会在基表中显示

4)or replace 覆盖创建视图选项(当创建的视图名已存在,该选项可以覆盖)
基于多表查询时,字段名有重复时,必须给视图里的字段取名

mysql> create table t1 select user,uid,shell from user limit 3;
Query OK, 3 rows affected (0.34 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> create table t2 select user,uid,homedir,shell from user limit 5;
Query OK, 5 rows affected (0.57 sec)
Records: 5  Duplicates: 0  Warnings: 0

mysql> select * from t1;
+--------+------+---------------+
| user   | uid  | shell         |
+--------+------+---------------+
| root   |    0 | /bin/bash     |
| bin    |    1 | /sbin/nologin |
| daemon |    2 | /sbin/nologin |
+--------+------+---------------+
3 rows in set (0.00 sec)

mysql> select * from t2;
+--------+------+----------------+---------------+
| user   | uid  | homedir        | shell         |
+--------+------+----------------+---------------+
| root   |    0 | /root          | /bin/bash     |
| bin    |    1 | /bin           | /sbin/nologin |
| daemon |    2 | /sbin          | /sbin/nologin |
| adm    |    3 | /var/adm       | /sbin/nologin |
| lp     |    4 | /var/spool/lpd | /sbin/nologin |
+--------+------+----------------+---------------+
mysql> select * from t1,t2 where t1.user=t2.user;
+--------+------+---------------+--------+------+---------+---------------+
| user   | uid  | shell         | user   | uid  | homedir | shell         |
+--------+------+---------------+--------+------+---------+---------------+
| root   |    0 | /bin/bash     | root   |    0 | /root   | /bin/bash     |
| bin    |    1 | /sbin/nologin | bin    |    1 | /bin    | /sbin/nologin |
| daemon |    2 | /sbin/nologin | daemon |    2 | /sbin   | /sbin/nologin |
+--------+------+---------------+--------+------+---------+---------------+
3 rows in set (0.00 sec)

mysql> create view v3 as select * from t1,t2 where t1.user=t2.user;
ERROR 1060 (42S21): Duplicate column name ‘user’
现在字段名重复,创建视图报错

mysql> create or replace view v3(t1user,t1uid,t1shell,t2user,t2uid,t2homedir) as select * from t1,t2 where t1.user=t2.user;
mysql> select * from v3;
+--------+-------+---------------+--------+-------+-----------+
| t1user | t1uid | t1shell       | t2user | t2uid | t2homedir |
+--------+-------+---------------+--------+-------+-----------+
| root   |     0 | /bin/bash     | root   |     0 | /root     |
| bin    |     1 | /sbin/nologin | bin    |     1 | /bin      |
| daemon |     2 | /sbin/nologin | daemon |     2 | /sbin     |
+--------+-------+---------------+--------+-------+-----------+
3 rows in set (0.01 sec)

mysql> create view v8 as select a.user,b.homedir from t1 a right join t2 b on a.uid=b.uid;
Query OK, 0 rows affected (0.02 sec)
mysql> select * from v8;
+--------+----------------+
| user   | homedir        |
+--------+----------------+
| root   | /root          |
| bin    | /bin           |
| daemon | /sbin          |
| NULL   | /var/adm       |
| NULL   | /var/spool/lpd |
+--------+----------------+

关于算法:
算法未定义时,值为UNDEFIBED 默认为 merge替换方式
temptables 具体化方式
具体化方式:先执行select基表 ,再执行查询视图 两次 速度慢
merge 替换方式只查询视图,速度块。

关于视图限制:
with check option 选项决定检查的范围
local 仅检查当前视图的限制
当没有指定限制时:默认为cascaded 同时满足基表的限制(默认值)
视图的基表也可以是一个视图 (所以此视图作为基表可以有限制)
如果修改视图未加限制时,视图内字段的值可以随意修改,但是当字段的值超出了本视图的限制范围,那么该字段在此视图中将不可见。

二 mysql存储过程:
存储过程,相当于是mysql语句组成的脚本
–指的是数据库中保存的一系列SQL命令的集合
–可以在存储过程中使用变量,条件,流程控制等

存储过程优点:
–提高性能
–可减轻网络负担
–可以防止对表的直接访问
–避免重复编写SQL操作

1 创建存储过程
1)在库里创建存储过程
delimiter
英 [ dɪ’lɪmɪtə ]美 [ dɪ’lɪmɪtə ]
n. 定界符,分隔符;

procedure
英 [ prəˈsi:dʒə® ]美 [ prəˈsidʒɚ ]
n. 程序,手续;工序,过程,步骤;诉讼程序,(议会的)议事程序;〈罕〉进行;

2)基本格式:

delimiter //
create procedure f()
begin
select * from db9.user limit 3;
create table if not existsdb9.a(id int);
end
//
mysql> create procedure f() begin select * from db9.user limit 3; create table if not exists a(id int); end //

将分隔符改回来
delimiter ;


调用 call f()


3)显示当前库下的存储状态

show procedure status;
select db,name,type from mysql.proc where name="存储过程名"
mysql> select body from mysql.proc where name="f"\G; 查看存储过程f的具体SQL语句
mysql> select db,name,type,body from mysql.proc where name="f";

4)创建f2存储过程,功能显示user表中 shell是/bin/bash用户的个数,调用存储过程f2:

mysql> delimiter //
mysql> create procedure f2() begin select count(user) from db9.user where shell="/bin/bash"; end //
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter ;
mysql> call f2;
+-------------+
| count(user) |
+-------------+
|           3 |
+-------------+
1 row in set (0.00 sec)

三 mysql变量类型
会话变量 全局变量: 会话变量的全局变量叫系统变量,使用set命令定义,全局变量的修改会影响到整个服务器,但是对会话变量的修改,只会影响到当前的会话 select @@localhost
用户变量: 在客户端连接到数据库服务的整个过程中都是有效的,当当前连接断开后所有用户变量失效 定义 set @变量名=值 输出 select @变量名
局部变量: 存储过程中的begin/end,其有效范围仅限于该语句块中,语句块执行完毕后,变量失效。 declare 专门用来定义局部变量
注意: 局部变量和参数变量调用时,变量名前不需要加@

1 一次数据库的连接为一次会话。会话变量session只对当前连接有效

ysql> set session sort_buffer_size = 40000;
Query OK, 0 rows affected (0.00 sec)

2 全局变量

mysql> show global variables like "%connect%";
+-----------------------------------------------+-------------------+
| Variable_name                                 | Value             |
+-----------------------------------------------+-------------------+
| character_set_connection                      | latin1            |
| collation_connection                          | latin1_swedish_ci |
| connect_timeout                               | 10                |
| disconnect_on_expired_password                | ON                |
| init_connect                                  |                   |
| max_connect_errors                            | 100               |
| max_connections                               | 151               |
| max_user_connections                          | 0                 |
| performance_schema_session_connect_attrs_size | 512               |
+-----------------------------------------------+-------------------+
9 rows in set (0.00 sec)
select @@hostname 

3 用户变量(自定义变量):

mysql> set @x=9;
Query OK, 0 rows affected (0.00 sec)

mysql> select @x;
+------+
| @x   |
+------+
|    9 |
+------+
1 row in set (0.00 sec)

mysql> set @name="yaya";

mysql> select @name;
+-------+
| @name |
+-------+
| yaya  |
+-------+

4 局部变量:
定义在存储过程里,只在存储过程执行时有效

mysql> delimiter //
mysql> create procedure f4() begin declare x int; set x=2; select x; select * from user where uid=x; end //
mysql> delimiter ;
mysql> call f4()
    -> ;
+------+
| x    |
+------+
|    2 |
+------+
1 row in set (0.00 sec)

+----+--------+--------+------+------+--------+---------+---------------+
| id | user   | passwd | uid  | git  | commet | homedir | shell         |
+----+--------+--------+------+------+--------+---------+---------------+
|  3 | daemon | x      |    2 |    2 | daemon | /sbin   | /sbin/nologin |
+----+--------+--------+------+------+--------+---------+---------------+

局部变量如果和用户变量同名,它们之间不会有任何影响
在语句块中,同名的变量,后赋值的生效。
注意:declare在语句块中定义变量时需要一块定义,不要跳行,变量前不需要加@符号

mysql> delimiter //
mysql> create procedure f7() begin declare y int default 1; select y; select count(id) into y from user; select y; end //
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;
mysql> call f7;
+------+
| y    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

+------+
| y    |
+------+
|   42 |
+------+
1 row in set (0.00 sec)

将查询结果赋值给自定义变量(用户变量):

mysql> select user into @x from user where id=1;
Query OK, 1 row affected (0.00 sec)

mysql> select @x;
+------+
| @x   |
+------+
| root |
+------+
1 row in set (0.00 sec)

5 参数类型:
可以有多个参数,结尾以逗号分隔,结构:(类型 参数名 数据类型)
如果不指定类型,默认为In类型
in 输入参数 :作用是给存储过程传值,必须在调用存储过程时赋值(传参),在存储过程中该参数的值不允许修改,默认类型为in
out 输出参数 : 该值可在存储过程内部被改变,并可返回
inout 输入/输出参数 : 调用时指定,并且可被改变和返回。

1)案例 in :

mysql> delimiter //                                                             
mysql> create procedure shelle(in shellname char(30)) begin  declare x int default 0;select x; select count(user) into x from user where shell=shellname; select x; end //
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;
mysql> call shelle("/sbin/nologin");
+------+
| x    |
+------+
|    0 |
+------+
1 row in set (0.01 sec)

+------+
| x    |
+------+
|   34 |
+------+
1 row in set (0.01 sec)

Query OK, 0 rows affected (0.01 sec)

mysql> call shelle("/bin/bash");
+------+
| x    |
+------+

|    0 |
+------+
1 row in set (0.00 sec)

+------+
| x    |
+------+
|    3 |
+------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)    

2)Out类型:
Outl类型在调用变量时不能直接给值,需要给一个变量来做占位符,无论这个变量是否有值 ,out类型的参数用于接收存储过程执行的结果。

mysql> delimiter //
mysql> create procedure p1(in shellname char(30),out number int) begin select count(user) into number from user where shell=shellname; select number; end //
Query OK, 0 rows affected (0.01 sec)

mysql> delimiter ;

mysql> call p1("/bin/bash",@z);
+--------+
| number |
+--------+
|      3 |
+--------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)     
~~~~~~~~~~~~~~~~~
mysql> call p1("/sbin/nologin",@q);       //变量随意调用,但必须是一个变量
+--------+
| number |
+--------+
|     34 |
+--------+
1 row in set (0.00 sec) 

3)in /out 类型:
存储过程调用时参数为一个有值的变量

mysql> delimiter //
mysql> create procedure p4(inout x char(30)) begin select x; select user into x from user where id=1;select x; end //
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;
mysql> set @a="qqq";
mysql> call p4(@a);
+------+
| x    |
+------+
| qqq |
+------+
1 row in set (0.00 sec)

+------+
| x    |
+------+
| root |
+------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

6 算数运算
运算符号及用法示例:
MySQL视图和存储过程详解_第1张图片

mysql> delimiter //
mysql>  create procedure say3(in bash char(20),in nologin char(20),out x int,out y int) begin declare z int; set z=0; select count(user) into x from user where shell=bash; select count(user) into y from user where shell=nologin; set z=x+y; select z; end //
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;
mysql> call say3("/bin/bash","/sbin/nologin",@q,@w);                            
+------+
| z    |
+------+
|   37 |
+------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

7 流程控制
1)条件判断

××单分支
begin
if 条件测试 then
代码
end fi ;
end

××双分支
begin
if条件测试
代码1
else
代码2
end if
end

mysql> delimiter //
mysql> create procedure say4(in x int) begin if 1=x then
    -> select * from user limit 1; else select * from user limit 1,1; end if ; end //
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;
mysql> call say4(1);
+----+------+--------+------+------+--------+---------+-----------+
| id | user | passwd | uid  | git  | commet | homedir | shell     |
+----+------+--------+------+------+--------+---------+-----------+
|  1 | root | x      |    0 |    0 | root   | /root   | /bin/bash |
+----+------+--------+------+------+--------+---------+-----------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

mysql> call say4(2);
+----+------+--------+------+------+--------+---------+---------------+
| id | user | passwd | uid  | git  | commet | homedir | shell         |
+----+------+--------+------+------+--------+---------+---------------+
|  2 | bin  | x      |    1 |    1 | bin    | /bin    | /sbin/nologin |
+----+------+--------+------+------+--------+---------+---------------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

定义名称为p3的存储过程,用户可以自定义显示user表记录的行数,若调用时用户没有输入行数,默认显示第1条记录

mysql> create procedure p3(in x char(5)) 
begin 
if x is null then 
set x=1; 
select * from user where id=x;
else 
select x; 
select * from user where id=x; 
end if; 
end //
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;
mysql> call p3(null) ;
+----+------+----------+------+------+---------+---------+-----------+
| id | name | password | uid  | gid  | comment | homedir | shell     |
+----+------+----------+------+------+---------+---------+-----------+
|  1 | root | x        |    0 |    0 | root    | /root   | /bin/bash |
+----+------+----------+------+------+---------+---------+-----------+

mysql> call p3(40);     
+------+
| x    |
+------+
| 40   |
+------+
1 row in set (0.00 sec)

+----+------+----------+------+------+---------+------------+-----------+
| id | name | password | uid  | gid  | comment | homedir    | shell     |
+----+------+----------+------+------+---------+------------+-----------+
| 40 | lisi | x        | 1000 | 1000 | lisi    | /home/lisi | /bin/bash |
+----+------+----------+------+------+---------+------------+-----------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 s

ec)

2)while循环结构
while 条件式循环 --反复测试条件,只要成立就执行命令序列
结构:
begin
while 条件判断 do
循环体
end while;
end //;

mysql> delimiter //
mysql> create procedure say7() begin declare x int default 1; while x<=10 do select * from user limit 1,1;set x=x+1; end while; end //
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;
mysql> call say7();

3)loop死循环–无条件,无限执行某一段代码
结构:
loop
循环体
end loop;

mysql> delimiter //
mysql> create procedure say8() begin declare x int default 1; loop select x; end loop; end //
mysql> delimiter ;
mysql> call say8();

4)repeat 条件式循环–当条件成立时结束循环(结构与while循环)
结构:
repeat
循环体
until 条件判断
end repeat

mysql> delimiter //
mysql> create procedure say9() begin declare x int default 1; repeat select * from user limit 1;set x=x+1; until x>=6 end repeat; end //
mysql> delimiter ;
mysql> call say9();

5)流程控制函数,控制循环结构的执行:
–leave 标签名 //跳出循环
–iterate 标签名 //放弃本次循环,执行下一次循环

##输出0-10 当值为4时跳过。(loab1为自己随意取的标签名)

mysql> delimiter //
mysql> create procedure say17() 
begin declare x int default 0; 
loab1:while x<=10 do 
if x=4 then 
set x=x+1; iterate loab1; 
end if; 
select x; set x=x+1; 
end while; 
end //
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;
mysql> call say17;

##输出1-15 当值为4时跳过,当值为13的时候结束循环 (loab1为自己随意取的标签名)

mysql> delimiter //
mysql> create procedure say21() begin declare x int default 1; loab1:while x<=15 do if x=8 then set x=x+1; iterate loab1; end if; select x; set x=x+1; if x=13 then leave loab1; end if; end while; end //
mysql> delimiter ;
mysql> call say20;

你可能感兴趣的:(数据库mysql)