The twenty-fourth to twentieth chapters
XXIV
Sometimes, the need to move forward or backward in one or more rows retrieved row, which is the cursor, the cursor is stored in a MySQL database queries on the server, not a SELECT statement, but the statement was retrieved result set
Cursor is mainly used for interactive applications, users can scroll through the data on the screen to browse or change
MySQL cursor can only be used for stored procedures (and function)
Use steps
1, the statement (define) the cursor
2, open the cursor, this process is the actual data retrieved
3, retrieved as required to obtain each row
4, close the cursor
Create, open and close the cursor and
CREATE PROCEDURE processorders()
BEGIN
-- 定义游标
DECLARE ordernumbers CURSOR
FOR
SELECT order_num FROM orders;
-- 打开游标
OPEN ordernumbers;
-- 关闭游标
CLOSE ordernumbers;
END;
Is to be noted OPEN xxx, CLOSE xxx statement should be stored in the procedure (between the BEGIN ... END), whether used alone being given
FETCH using separate visits each row, the row pointer moves forward inside the cursor, so that the next FETCH statement retrieves the next line to ensure that no repeat read
CREATE PROCEDURE processorders()
BEGIN
--定义一个局部变量
DECLARE o INT;
DECLARE ordernumbers CURSOR
FOR
SELECT order_num FROM orders;
OPEN ordernumbers;
--检索第一行
FETCH ordernumbers INTO o;
CLOSE ordernumbers;
END;
The first row of the retrieved stored into local variables o but not processed
Cyclic retrieve data from the first row to the last row
CREATE PROCEDURE processorders()
BEGIN
--定义局部变量,必须在定义游标之前定义
DECLARE done BOOLEAN DEFAULT 0;
DECLARE o INT;
DECLARE ordernumbers CURSOR
FOR
SELECT order_num FROM orders;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
OPEN ordernumbers;
--循环每一行
REPEAT
FETCH ordernumbers INTO o;
UNTIL done END REPEAT;
CLOSE ordernumbers;
END;
The present embodiment is repeatedly executed until done FETCH is true, it is done with a defined start DEFAULT 0, and when done As is true
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
This statement defines a CONTINUE HANDLER, when SQLSTATE '02000' occurs, SET done = 1, SQLSTATE '02000' is a condition not found, this condition occurs when there are no more rows due REPEAT loop can not continue for
Processing data retrieved
-- 上一章学习过的存储过程,待会要用到
CREATE PROCEDURE ordertotal(
IN onumber INT,
IN taxable BOOLEAN,
OUT ototal DECIMAL(8,2)
) COMMENT 'Obtain order total, optionally adding tax'
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 taxable THEN
SELECT total+(total/100*taxrate) INTO total;
END IF;
SELECT total INTO ototal;
END;
-- 如果已经存在该过程,先删除
DROP PROCEDURE IF EXISTS processorders;
CREATE PROCEDURE processorders()
BEGIN
-- Declare local variables
DECLARE done BOOLEAN DEFAULT 0;
DECLARE o INT;
DECLARE t DECIMAL(8, 2);
-- Declare the cursor
DECLARE ordernumbers CURSOR
FOR
SELECT order_num FROM orders;
-- Declare continue handler
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
-- 如果表已经存在,先删除
DROP TABLE IF EXISTS ordertotals;
-- 创建表
CREATE TABLE IF NOT EXISTS ordertotals (order_num INT, total DECIMAL(8, 2));
-- Open the cursor
OPEN ordernumbers;
-- Loop through all rows
REPEAT
-- 取第一行
FETCH ordernumbers INTO o;
-- done仍为0
IF NOT done THEN
-- 调用存储过程,将结果赋值给t
CALL ordertotal(o, 1, t);
-- 插入一行到新建的表中
INSERT INTO ordertotals(order_num, total)
VALUES(o, t);
END IF;
-- End of loop
UNTIL done END REPEAT;
-- Close the cursor
CLOSE ordernumbers;
END;
-- CREATE只相当于声明一个过程,CALL是调用,若没有该语句而执行接下来的SELECT语句,报错:表不存在
CALL processorders;
-- 查看该表
SELECT *
FROM ordertotals;
We have added a variable t, used to store each order with tax together, the results ordertotals table stores generated
Here the code with different code books, a bug in the code book, resulting in the output line of the last two results, a bug in code look
REPEAT
FETCH ordernumbers INTO o;
CALL ordertotal(o, 1, t);
INSERT INTO ordertotals(order_num, total)
VALUES(o, t);
UNTIL done END REPEAT;
Probably for the following reasons, after the final row, back to the beginning of the cycle, MySQL attempts to FETCH a new line, but at this time has no more lines can be retrieved, this time done to 1, in theory, it should end error cycles, but not so MySQL, but to continue the cycle, and O, the value of a cycle value t, resulting in the table have duplicate the last two rows, since after this cycle is done 1 therefore exit the loop, which is why cycling body's own code to judge one more time, when it is no longer done for the subsequent operations 1