mysql 1337 游标嵌套_MySQL笔记(六)游标练习

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

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

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

DROP PROCEDURE IF EXISTSshow_female_details;

DELIMITER//

CREATE PROCEDUREshow_female_details()BEGIN

--用于保存 FETCH 结果的变量

DECLARE employee_no VARCHAR(8);DECLARE employee_name VARCHAR(10);DECLARE sex CHAR(1);DECLAREbirthday DATE;DECLARE address VARCHAR(50);DECLARE telephone VARCHAR(20);DECLAREhiredate 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 * FROMemployee;OPENemployee_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;FETCHemployee_detailsINTOemployee_no, employee_name, sex, birthday, address, telephone, hiredate, department, headship, salary;IF sex = 'F' THEN

SELECTemployee_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 EXISTScal_sum;

DELIMITER//

CREATE PROCEDUREcal_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 FROMorder_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 的声明位置很苛刻。。。

OPENorder_nos;WHILE (NOTdone) DO--SELECT VERSION();

--SET done:=1; -- 测试专用

FETCH order_nos INTOorder_num;UPDATEorder_masterSET order_sum =(SELECT SUM(quantity*price)FROMorder_detailGROUP BYorder_detail.order_noHAVING 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 EXISTSproSearchCustomer;

DELIMITER//

CREATE PROCEDUREproSearchCustomer(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

SELECTcustomer_name,

address,

y.order_no,

product_no,

quantity,

priceFROMcustomer xLEFT JOIN order_master y ON x.customer_no =y.customer_noLEFT JOIN order_detail z ON y.order_no =z.order_noWHEREx.customer_no=customer_no_inORDER BYproduct_no;DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;OPENsales_records;WHILE (NOTdone) DOFETCHsales_recordsINTOcustomer_name_temp, address_temp, order_no_temp, product_no_temp, quantity_temp, price_temp;SELECTcustomer_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 EXISTSgetInfo;

DELIMITER//

CREATE PROCEDUREgetInfo()BEGIN

DECLARE no_ INT;DECLARE name_ VARCHAR(50);DECLARE done INT DEFAULT 0;DECLARE infos CURSOR FOR SELECT id, name FROMcustomer;DECLARE EXIT HANDLER FOR NOT FOUND SET done = 1;OPENinfos;WHILE (NOTdone) DOFETCH infos INTOno_, name_;SELECTno_, name_;END WHILE;END //DELIMITER ;

/

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

CREATE TRIGGER ins_transaction BEFORE INSERT ONaccount

FOREACH 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'

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL 支持使用游标进行数据操作,可以使用嵌套循环实现对多个表的操作。下面是一个示例代码,演示如何使用游标嵌套循环实现对两个表的操作。 假设有两个表 A 和 B,其中 A 表包含字段 id 和 name,B 表包含字段 id 和 value,现在需要将两个表中相同 id 的记录拼接在一起,得到一个新的表 C,包含字段 id、name 和 value。 ``` DECLARE cur_a CURSOR FOR SELECT id, name FROM A; DECLARE cur_b CURSOR FOR SELECT id, value FROM B; DECLARE done INT DEFAULT FALSE; DECLARE a_id INT; DECLARE a_name TEXT; DECLARE b_id INT; DECLARE b_value TEXT; CREATE TABLE C ( id INT PRIMARY KEY, name TEXT, value TEXT ); OPEN cur_a; FETCH cur_a INTO a_id, a_name; WHILE NOT done DO IF a_id IS NOT NULL THEN OPEN cur_b; FETCH cur_b INTO b_id, b_value; WHILE NOT done DO IF b_id IS NOT NULL THEN IF a_id = b_id THEN INSERT INTO C (id, name, value) VALUES (a_id, a_name, b_value); END IF; ELSE SET done = TRUE; END IF; FETCH cur_b INTO b_id, b_value; END WHILE; CLOSE cur_b; END IF; FETCH cur_a INTO a_id, a_name; END WHILE; CLOSE cur_a; ``` 这段代码中,首先定义了两个游标,分别对应表 A 和表 B。然后使用两个循环,分别遍历表 A 和表 B 中的记录。在表 A 的循环中,对于每一条记录,都打开游标 cur_b,然后在表 B 中查找相同 id 的记录,并将它们插入到表 C 中。当表 B 的游标遍历完所有记录后,关闭游标 cur_b,继续遍历表 A 的下一条记录。最后关闭游标 cur_a,完成操作。 需要注意的是,游标嵌套循环可能会导致性能问题,特别是在处理大量数据时。因此,在实际应用中,应该尽量避免使用游标嵌套循环,而是使用其他方式进行数据操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值