6.《MySQL必知必会》视图,存储过程,游标与触发器

注:博客中总结《MySQL必知必会》中的知识点,第22,23,24,25章的核心内容;

涉及到的操作符:VIEW,PROCEDURE,CALL,DECLARE,IF,REPEAT,END,FETCH,TRIGGER;

书中用到的表的介绍及其脚本文件:《Mysql必知必会》中表的介绍

使用视图

视图是虚拟的表(我的理解就是想C++中的引用),它的好处有:
- 重用SQL语句;
- 简化复杂的SQL操作;
- 使用表的组成部分而不是整个表;
- 保护数据
- 更改数据格式和表示;

1.使用视图简化复杂的联结
CREARE VIEW productcustomers AS
SELECT cust_name, cust_contact, prod_id
FROM customers, orders, orderitems
WHERE customers.cust_id = orders.cust_id
  AND orderitems.order_num = orders.order_num;

-- 这样以后检索订购TNT2的客户,可如下进行:
SELECT cust_name, cust_contact
FROM productcutomers
WHERE prod_id = 'TNT2';
2.用视图重新格式化检索出的数据
CREATE VIEW vendorlocations AS
SLECT Concat(RTrim(vend_name),'(',RTrim(vend_country),')')
      AS vend_title
FROM vendors
ORDER BY vend_name;

-- 直接检索即可
SELECT *
FROM vendorlocations;
3.用视图过滤不想要的数据
CREATE VIEW customermaillist AS
SELECT cust_id, cust_name, cust_email
FROM customers
WHERE cust_email IS NOT NULL;

-- 直接检索即可
SELECT *
FROM customermaillist;
4.用视图过滤不想要的数据
CREATE VIEW customermaillist AS
SELECT cust_id, cust_name, cust_email
FROM customers
WHERE cust_email IS NOT NULL;

-- 直接检索即可
SELECT *
FROM customermaillist;
5.使用视图与计算字段
CREATE VIEW orderitemsexpended AS
SELECT prod_id,
       quantity,
       item_price,
       quantity*item_price AS expanded_price
FROM orderitems;

-- 直接检索即可
SELECT *
FROM orderitemsexpanded
WHERE order_num = 20005;
6.更新视图

如果视图定义有一下操作,则不能进行视图的更新;
- 分组
- 联结
- 子查询
- 并
- 聚集函数

使用存储过程

类似于函数;

1.存储过程的好处

存储过程的3个主要好处,即简单,安全和高性能;

2.使用存储过程
-- 使用PROCEDURE定义存储过程;
CREATE PROCEDURE productpricing()
BEGIN
    SELECT AVG(prod_price) AS priceaverage
    FROM products;
END;

-- 使用CALL调用存储过程;
CALL productpricing();
3.删除存储过程
DROP PROCEDURE productpricing;
4.使用参数(只有输出参数)
-- 使用PROCEDURE定义只带输出参数的存储过程;
CREATE PROCEDURE productpricing(
    OUT pl DECIMAL(8,2),
    OUT ph DECIMAL(8,2),
    OUT pa DECIMAL(8,2)
)
BEGIN
    SELECT Min(prod_price)
    INTO pl
    FROM products;
    SELECT Max(prod_price)
    INTO ph
    FROM products;
    SELECT AVG(prod_price)
    INTO pa
    FROM products;
END;

-- 使用CALL调用存储过程;
CALL productpricing(@pricelow,
                    @pricehigh,
                    @priceaverage);

-- 显示检索出的产品最低,最高,平均价格
SELECT @pricehigh,@pricelow,@priceaverage;
5.使用参数(有输入,输出参数)
-- 使用PROCEDURE定义带输入,输出参数的存储过程;
CREATE PROCEDURE ordertotal(
    IN onumber INT,
    OUT ototal DECIMAL(8,2)
)
BEGIN
    SELECT Sum(item_price*quantity)
    FROM orderitems
    WHERE order_num = onumber
    INTO ototal;
END;

-- 使用CALL调用存储过程;
CALL ordertotal(20005, @total);

-- 显示检索出的产品最低,最高,平均价格
SELECT @total;

-- 这样还可以方便的得到另一个订单的合计过程
CALL ordertotal(20009,@total);
SELECT @total;
6.建立智能存储过程

增加 IF 判断

-- 定义智能存储过程
CREATE PROCEDURE ordertotal(
    IN onumber INT,
    IN taxable BOOLEN,
    OUT otatol DECIMAL(8,2)
)
BEGIN
    -- 声明变量
    DECLARE total DECIMAL(8,2);
    DECLARE taxrate INT DEFAULT 6;

    -- 得到全部订单
    SELECT Sum(item_price*quantity)
    FROM orderitems
    WHERE order_num=onumber
    INTO total;

    -- IF 判断
    IF taxable THEN
        SELECT total+(total/100*taxarate) INTO total;
    END IF;
    SELECT total INTO ototal;
END;

CALL ordertotal(20005,0,@tatol);
SELECT #total;

CALL ordertotal(20005,1,@tatol);
SELECT #total;
7.检查存储过程
-- 显示创建存储过程的CREATE语句;

SHOW CREATE PROCEDURE ordertotal;

使用游标

游标只能用于存储过程
游标的作用:在检索出来的行中可以前进或者后退一行或多行;(类似于指针?)

1.创建游标
CREATE PROCEDURE processorders()
BEGIN
    DECLARE ordernumbers CURSOR  -- 声明游标
    FOR
    SELECT order_num FROM orders;
END;
2.打开和关闭游标
-- 打开游标
OPEN ordernumbers;

-- 关闭游标
CLOSE ordernumbers;
3.使用游标数据
CREATE PROCEDURE processorders()
BEGIN
    -- 声明局部变量
    DECLARE done BOOLEN DEFAULT 0;
    DECLARE o INT;
    DECLARE t DECIMAL(8,2);

    -- 声明游标
    DECLARE ordernumbers CURSOR
    FOR
    SELECT order_num FROM order;

    -- 定义是否终止的条件
    DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;

    -- 创建表
    CREATE TABLE IF NOT EXISTS ordertotals
       (order_num INT, total DECIMAL(8,2));

    -- 打开游标
    OPEN ordernumbers;

    -- 进入循环
    REPEAT
        FETCH ordernumbers INTO o; -- 得到游标具体的值
        CALL ordertotal(o, 1 ,t);  -- 调用存储过程
        INSERT INTO ordertotals(order_num, total)  -- 插入到新建的表中
        VALUES(o, t);
    UNTIL done END REPEAT;

    -- 关闭游标
    CLOSE ordernumbers;
END

-- 检索新建的表
CALL processorders();
SELECT * FROM ordertotals;

使用触发器

触发器的作用:需要某条语句在事件发生时自动执行

1.创建触发器

只有表支持触发器,视图不支持。在创建触发器时,需要给出四条信息:
- 唯一的触发器名;
- 触发器关联的表;
- 触发器应该响应的活动(DELETE,INSERT或UPDATE)
- 触发器何时执行(处理之前或之后);

CREATE TRIGGER newproduct AFTER INSERT ON PRODUCTS
FOR EACH ROW SELECT 'Product added';
-- 创建了一个newproduct新触发器。在INSERT语句成功执行之后执行,并对每个插入行执行。在这个例子中,文本‘Product added’在每个插入的行显示一次;
2.删除触发器
DROP TRIGGER newproduct;
3.INSERT触发器
-- 定义INSERT触发器
CREATE TRIGGER neworder AFTEr INSERT ON orders
FOR EACH ROW SELECT NEW.order_num;

-- 测试触发器
INSERT INTO orders(order_date, cust_id)
VAlUES(Now(), 10001);
4.DELETE触发器
-- 定义DELETE触发器,在DELETE语句中可以引用一个OLD的只读虚拟表。可以访问被删除的行;
CREATE TRIGGER deleteorder BEFORE DELETE ON orders
FOR EACH ROW
BEGIN
    INSERT INTO archive_orders(order_num, order_date, cust_id)
    VALUES(OLD.order_num, OLD.order_date, OLD.cust_id);
END;
-- 在任意订单被删除之前执行此触发器。见删除之保存删除行;
5.UPDATE触发器
-- 定义DELETE触发器,在UPDATE语句中可以引用一个OLD的只读虚拟表访问以前的值。
-- 还会引用一个NEW的虚拟表访问新更新的值;
CREATE TRIGGER updatevendor BEFORE UPDATE ON vendors
FOR EACH ROW SET NEW.vend_state = Upper(NEW.vend_state);
-- 任何数据净化都需要在UPDATE语句之前进行,每次更新一行时,都会通过Upper();
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值