今天的内容相当纠结,后面几章的标题分别是《使用视图》、《使用存储过程》、《使用游标》、《使用触发器》、《管理事务处理》。看到这些标题很多都是久闻大名却未曾谋面的,有的甚至听都没听过(@_@),但是千万不能被陌生的东西吓住,我一定可以征服它们,今天先看了三章,总结一下。
第22章:使用视图
什么是视图?视图就是VIEW,哈哈,根据之前学过的操作意识,莫非是要用CREATE来创建?BINGO~完全正确,正是CREATE VIEW,同理可以得删除视图用DROP VIEW 。但是这个VIEW是用来干嘛的呢?看完这一章的内容之后我觉得视图的最大的用就在于:重用SQL语句和简化复杂的SQL操作。至于书中提到的关于用户授权,数据保护之类的由于不是很熟悉,所以没什么感觉,只有先MARK一下,以后在实践中再加强了。那我总结一下我最有感觉的两个作用,先看下面的例子:
-- 重点是第一句
CREATE VIEW myview AS
SELECT t.user_id*t.user_id AS user_num,t.user_add,b.book_type
FROM test AS t,books AS b
WHERE t.user_id=b.user_id
AND t.user_id>3;
看到上面的语句有什么感觉?好吧,不知所云,我懂的,我只是随便找找东西而已,那如果我每次都要用这么复杂的语句…………还好我加上了第一句
CREATE VIEW myview AS
创建了一个视图,有什么用呢?看下面的查询
SELECT *
FROM myview;
如果你测试过,那就会知道上面的视图查询的结果就上当于第一部的联结查询的结果,这样的话就可以不用每次都敲那么多代码,把常用的复杂的查询创建视图就OK了。但是
视图本身并没有数据,使用查询语句得到的数据还是来自于原表。所以也可以在视图中对数据进行更新和删除,这样的话其实是直接对原表进行了修改,所以也要小心行事,
一般也不推荐在视图中对数据进行修改。
如果在视图定义中有以下操作,则不能进行视图数据更新:
1、分组(使用GROUP BY 和 HAVING)
2、联结
3、子查询
4、并;
5、聚集函数
6、DISTINCT
7、导出(计算)
第23章:使用存储过程
看完这一章以后我感觉所谓的存储过程就是类似于程序语言中的函数,先使用CREATE PROCEDURE语句定义好存储过程,然后使用CALL关键字可以调用存储过程,删除某个存储过程用DROP PROCEDURE,看例子:
-- 这里定义了一个PROCEDURE,后面跟着它的参数
CREATE PROCEDURE myprocedure(
-- IN是接收的参数
IN b_id_in int,
-- OUT是返回的参数
OUT b_id int,
OUT u_id int,
OUT b_type VARCHAR(20)
)
-- PROCEDURE 开始
BEGIN
-- 用INTO把参数给返回参数传值
SELECT MAX(book_id) INTO b_id
FROM books;
SELECT MIN(user_id) INTO u_id
FROM books;
SELECT book_type INTO b_type
FROM books
WHERE book_id=b_id_in;
-- PROCEDURE 结果
END;
-- 上面的PROCEDURE中一个需要注意的地方,那就是在倒数第二行的最后一个字符";"上。
-- 由于MySQL默认的语句分隔符就是;,所以如果你在命令中输入以上命令可以会导致错误
-- 因为它在接收到;之后就把这个语句当作是完整的语句执行了,但这样显然不行
-- 解决办法就是临时改变命令行的语句分隔符,用法如下
-- 用DELIMITER关键字把语句分隔符改为"//",其实除了不能用转义符"\",其它都行
DELIMITER //
CREATE PROCEDURE test()
BEGIN
SELECT *
FROM test;
END//
-- 语句结束了再把语句分隔符转回来,当然如果是使用图形界面就没有这个问题
DELIMITER ;
定义好了存储过程,就可以直接调用了
-- 使用CALL关键字调用储存过程,注意参数的一一对应,而且OUT参数前要加“@”
CALL myprocedure(3,@max_book_id,@min_user_id,@b_type);
-- 直接用SELECT显示调用结果
SELECT @max_book_id,@min_user_id,@b_type;
用SHOW PROCEDURE STATUS可以获得存储过程的列表,可以用DROP PROCEDURE删除你不需要的存储过程。
第24章:使用游标
在之前的学习中我们都是通过某些过滤条件然后检索出一组结果集,但是并没有办法说检索第一行,下一行或者是前10行的数据,这个时候游标这可以完成这项工作了。直接来看例子吧。
-- 先创建一个存储过程,用user_id检索test表中信息
CREATE PROCEDURE mypro(
IN id int
)
BEGIN
SELECT *
FROM test
WHERE user_id=id;
END;
接下来是游标的使用方法,我尽可能的解释清楚,不过对于有编程经验的人来说应该问题不大
-- 创建的这个存储过程主要是把test表中的user_id循环检索出来
-- 再通过user_id调用存储过程mypro()来得到表中的所有信息
CREATE PROCEDURE cursorpro()
BEGIN
-- 定义变量flag
DECLARE flag BOOLEAN DEFAULT 0;
-- 定义变量 id
DECLARE id int;
-- 定义名字为mycursor的游标
DECLARE mycursor CURSOR
FOR
SELECT user_id FROM test;
-- 定义CONTINUE HANDLER,就像循环的控制变量
-- SQLSTATE ‘02000’是一个未找到条件,意思是说没有数据了那就SET flag=1;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET flag=1;
-- 打开游标
OPEN mycursor;
-- 使用循环语句与游标来遍历一个表
REPEAT
-- 在游标被打开后,FETCH语句用来分别访问它的每一行,每次使用FETCH,会向前移动游标中的内部行指针
-- 下面这句把SELECT语句检索到的user_id放到id中去
FETCH mycursor INTO id;
-- 调用另一个存储过程mypro()
CALL mypro(id);
UNTIL flag END REPEAT;
-- 在使用完游标后要关闭游标,这样才能释放游标使用的内部内存和资源
-- 在关闭游标后,下次的使用不用重新定义游标,只要打开游标就可以使用了
CLOSE mycursor;
END;
最后只要直接检索游标内容就可以了
CALL cursorpro();
SELECT *
FROM mycursor;
以上便是游标的基本用法,以后有机会会加深这部分的学习。