MySQL笔记(六)游标练习

23.3.1 Trigger Syntax and Examples

意义不明的几道练习,留着备用。

感觉不好写,而且难以调试。。不知道以后会不会有实际的应用场景。

环境:MySQL 笔记(三)由 txt 文件导入数据

1、利用游标查找所有女业务员的基本情况

DROP PROCEDURE IF EXISTS show_female_details;
DELIMITER //
CREATE PROCEDURE show_female_details()
BEGIN
    -- 用于保存 FETCH 结果的变量
    DECLARE employee_no VARCHAR(8);
    DECLARE employee_name VARCHAR(10);
    DECLARE sex CHAR(1);
    DECLARE birthday DATE;
    DECLARE address VARCHAR(50);
    DECLARE telephone VARCHAR(20);
    DECLARE hiredate DATE;
    DECLARE department VARCHAR(30);
    DECLARE headship VARCHAR(10);
    DECLARE salary DECIMAL(8,2);
    DECLARE cnt INT DEFAULT 0;
    -- 循环变量
    DECLARE i INT DEFAULT 0;
    -- 声明游标
    DECLARE employee_details CURSOR FOR SELECT * FROM employee;
    OPEN employee_details;
    -- ERROR 1337 (42000): Variable or condition declaration after cursor or handler declaration
    -- employee 表的元组数
    SELECT COUNT(*) FROM employee INTO cnt; -- 如果放在游标声明之前将报错。
    
    WHILE i < cnt DO -- 意外发现:TAB控制缩进报错,空格缩进不报错
     SET i:=i+1;
     FETCH employee_details
     INTO employee_no, employee_name, sex, birthday, address, telephone, hiredate, department, headship, salary;
     IF sex = 'F' THEN
      SELECT employee_no, employee_name, sex, birthday, address, telephone, hiredate, department, headship, salary;
     END IF;
    END WHILE;
END // 
DELIMITER ;
CALL show_female_details();
-- imooc 为什么使用存储过程 补充

/

2、利用游标修改orderMaster表中的Ordersum的值

DROP PROCEDURE IF EXISTS cal_sum;
DELIMITER //
CREATE PROCEDURE cal_sum()
BEGIN
    -- 用于保存 FETCH 结果的变量
    DECLARE order_num VARCHAR(12);
    
    DECLARE done INT DEFAULT 0;
    -- 当抛出 not find 的时候把 done 改成 true
    -- 什么时候抛出 not find 呢?在游标 FETCH 不到数据的时候
    DECLARE order_nos CURSOR FOR SELECT order_no FROM order_master;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;  
    -- ERROR 1338 (42000): Cursor declaration after handler declaration
    -- ERROR 1337 (42000): Variable or condition declaration after cursor or handler declaration
    -- 总之 cursor 的声明位置很苛刻。。。
    
    OPEN order_nos;
    
    WHILE (NOT done) DO
     -- SELECT VERSION();
     -- SET done:=1; -- 测试专用
     FETCH order_nos INTO order_num;
     UPDATE order_master 
     SET order_sum = (
      SELECT SUM(quantity*price)
      FROM order_detail
      GROUP BY order_detail.order_no
      HAVING order_detail.order_no = order_num
     )
     WHERE order_master.order_no = order_num;
    END WHILE;
END // 
DELIMITER ;
CALL cal_sum();

 /

3、请使用游标和循环语句编写一个存储过程proSearchCustomer,根据客户编号,查询该客户的名称、地址以及所有与该客户有关的销售记录,销售记录按商品分组输出。

DROP PROCEDURE IF EXISTS proSearchCustomer;
DELIMITER //
CREATE PROCEDURE proSearchCustomer(
    IN customer_no_in varchar(9)
)
BEGIN
    DECLARE customer_name_temp varchar(40);
    DECLARE address_temp varchar(40);
    DECLARE order_no_temp varchar(12);
    DECLARE product_no_temp varchar(9);
    DECLARE quantity_temp int(11);
    DECLARE price_temp decimal(7,2);
    
    DECLARE done INT DEFAULT 0;
    DECLARE sales_records CURSOR FOR
     SELECT
      customer_name,
      address,
      y.order_no,
      product_no,
      quantity,
      price
     FROM
      customer x
      LEFT JOIN order_master y ON x.customer_no = y.customer_no
      LEFT JOIN order_detail z ON y.order_no = z.order_no
     WHERE
      x.customer_no = customer_no_in
     ORDER BY 
      product_no;    
     DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
    
    OPEN sales_records;
    
    WHILE (NOT done) DO
     FETCH sales_records
     INTO customer_name_temp, address_temp, order_no_temp, product_no_temp, quantity_temp, price_temp;
     SELECT customer_name_temp, address_temp, order_no_temp, product_no_temp, quantity_temp, price_temp;
    END WHILE;
END // 
DELIMITER ;
CALL proSearchCustomer('c2005001');

4、随便放在这儿。。

-- 第三题
DROP PROCEDURE IF EXISTS getInfo;
DELIMITER //
CREATE PROCEDURE getInfo()
BEGIN
    DECLARE no_ INT;
    DECLARE name_ VARCHAR(50);
    
    DECLARE done INT DEFAULT 0;
    
    DECLARE infos CURSOR FOR SELECT id, name FROM customer;
    DECLARE EXIT HANDLER FOR NOT FOUND SET done = 1;  
    
    OPEN infos;
    
    WHILE (NOT done) DO
     FETCH infos INTO no_, name_;
     SELECT no_, name_;
    END WHILE;
END // 
DELIMITER ;

 /

5、印象中在《MYSQL CRASH COURSE》里有提到一张表最多可以有 6 个触发器,现在的版本已经能够在一张表上建立数量不限个触发器:

CREATE TRIGGER ins_transaction BEFORE INSERT ON account
FOR EACH ROW PRECEDES ins_sum
SET
@deposits = @deposits + IF(NEW.amount>0,NEW.amount,0),
@withdrawals = @withdrawals + IF(NEW.amount<0,-NEW.amount,0);    

PRECEDES 和 FOLLOWS 都是书上没提到的东西,规定了触发动作、触发时间都相同的触发器的执行顺序。旧版本不能用哦:

ERROR 1235 (42000): This version of MySQL doesn't yet support 'multiple triggers with the same action time and event for one table'
原文地址:https://www.cnblogs.com/xkxf/p/9046541.html