MySQL 游标出错的存储过程
MySQL Stored Procedures with cursor giving error
我试图通过从以前的读数中减去当前读数来计算基于当前使用的单位的数量,但我似乎有一些语法错误和逻辑问题。请帮忙。
(我知道它可以在插入语句本身中完成,但我需要了解游标的工作原理)
ERROR 1064 (42000) at line 22 in file: 'DEF.sql': You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LOOP:
FETCH curBill INTO cno, pr, cr;
IF !flag THEN
SET unt = cr-pr;
EL' at line 13
MariaDB v10.4.8
CREATE DATABASE Random;
USE Random;
CREATE TABLE Customer(
`c_no` INT,
`name` VARCHAR(40),
`previous_reading` INT,
`current_reading` INT,
`amount` INT DEFAULT 0
);
INSERT INTO Customer (`c_no`, `name`, `previous_reading`,`current_reading`)
VALUES
(101, 'Smith', 90, 120),
(201, 'George', 30, 250),
(301, 'Philip', 120, 200),
(401, 'Jasper', 10,390);
SELECT * FROM Customer;
DELIMITER $$ ;
CREATE PROCEDURE e_bills()
BEGIN
DECLARE flag INT DEFAULT 0;
DECLARE cno INT;
DECLARE pr, cr, amt, unt DOUBLE;
DECLARE curBill
CURSOR FOR
SELECT `c_id`, `previous_reading`, `current_reading`
FROM Customer;
DECLARE CONTINUE HANDLER FOR NOT found SET flag = 1;
OPEN curBill;
calUnit LOOP:
FETCH curBill INTO cno, pr, cr;
IF !flag THEN
SET unt = cr-pr;
ELSE IF flag THEN
LEAVE calUnit;
END IF;
IF (unt <= 100) THEN
SET amt = unt*2;
ELSE IF (unt >= 101 AND unt <= 200) THEN
SET amt = unt*2.5;
ELSE IF (unt > 201 AND unt <= 300) THEN
SET amt = unt*3;
ELSE IF (unt > 301) THEN
SET amt = unt*4;
END IF;
UPDATE Customer
SET `amount`=amt;
END LOOP;
CLOSE curBill;
END $$
DELIMITER ; $$
CALL e_bills();
SELECT * FROM Customer;
DROP DATABASE Random;
大量语法错误,如果您不在更新语句中使用 where 子句,将更新所有客户。
drop table if exists t;
CREATE TABLE t(
`c_no` INT,
`name` VARCHAR(40),
`previous_reading` INT,
`current_reading` INT,
`amount` INT DEFAULT 0
);
INSERT INTO t (`c_no`, `name`, `previous_reading`,`current_reading`)
VALUES
(101, 'Smith', 90, 120),
(201, 'George', 30, 250),
(301, 'Philip', 120, 200),
(401, 'Jasper', 10,390);
drop procedure if exists p;
DELIMITER $$
CREATE PROCEDURE p()
BEGIN
DECLARE flag INT DEFAULT 0;
DECLARE cno INT;
DECLARE pr, cr, amt, unt DOUBLE;
DECLARE curBill
CURSOR FOR
SELECT c_no, `previous_reading`, `current_reading`
FROM t;
DECLARE CONTINUE HANDLER FOR NOT found SET flag = 1;
OPEN curBill;
calUnit: LOOP
FETCH curBill INTO cno, pr, cr;
IF flag <> 1 THEN
SET unt = cr-pr;
ELSE
LEAVE calUnit;
END IF;
IF (unt <= 100) THEN
SET amt = unt*2;
ELSEIF (unt >= 101 AND unt <= 200) THEN
SET amt = unt*2.5;
ELSEIF (unt > 201 AND unt <= 300) THEN
SET amt = unt*3;
ELSEIF (unt > 301) THEN
SET amt = unt*4;
END IF;
UPDATE t
SET `amount`=amt
where c_no = cno;
END LOOP;
CLOSE curBill;
END $$
DELIMITER ;
CALL p();
SELECT * FROM t;
+------+--------+------------------+-----------------+--------+
| c_no | name | previous_reading | current_reading | amount |
+------+--------+------------------+-----------------+--------+
| 101 | Smith | 90 | 120 | 60 |
| 201 | George | 30 | 250 | 660 |
| 301 | Philip | 120 | 200 | 160 |
| 401 | Jasper | 10 | 390 | 1520 |
+------+--------+------------------+-----------------+--------+
4 rows in set (0.00 sec)
我试图通过从以前的读数中减去当前读数来计算基于当前使用的单位的数量,但我似乎有一些语法错误和逻辑问题。请帮忙。
(我知道它可以在插入语句本身中完成,但我需要了解游标的工作原理)
ERROR 1064 (42000) at line 22 in file: 'DEF.sql': You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LOOP:
FETCH curBill INTO cno, pr, cr; IF !flag THEN SET unt = cr-pr; EL' at line 13
MariaDB v10.4.8
CREATE DATABASE Random;
USE Random;
CREATE TABLE Customer(
`c_no` INT,
`name` VARCHAR(40),
`previous_reading` INT,
`current_reading` INT,
`amount` INT DEFAULT 0
);
INSERT INTO Customer (`c_no`, `name`, `previous_reading`,`current_reading`)
VALUES
(101, 'Smith', 90, 120),
(201, 'George', 30, 250),
(301, 'Philip', 120, 200),
(401, 'Jasper', 10,390);
SELECT * FROM Customer;
DELIMITER $$ ;
CREATE PROCEDURE e_bills()
BEGIN
DECLARE flag INT DEFAULT 0;
DECLARE cno INT;
DECLARE pr, cr, amt, unt DOUBLE;
DECLARE curBill
CURSOR FOR
SELECT `c_id`, `previous_reading`, `current_reading`
FROM Customer;
DECLARE CONTINUE HANDLER FOR NOT found SET flag = 1;
OPEN curBill;
calUnit LOOP:
FETCH curBill INTO cno, pr, cr;
IF !flag THEN
SET unt = cr-pr;
ELSE IF flag THEN
LEAVE calUnit;
END IF;
IF (unt <= 100) THEN
SET amt = unt*2;
ELSE IF (unt >= 101 AND unt <= 200) THEN
SET amt = unt*2.5;
ELSE IF (unt > 201 AND unt <= 300) THEN
SET amt = unt*3;
ELSE IF (unt > 301) THEN
SET amt = unt*4;
END IF;
UPDATE Customer
SET `amount`=amt;
END LOOP;
CLOSE curBill;
END $$
DELIMITER ; $$
CALL e_bills();
SELECT * FROM Customer;
DROP DATABASE Random;
大量语法错误,如果您不在更新语句中使用 where 子句,将更新所有客户。
drop table if exists t;
CREATE TABLE t(
`c_no` INT,
`name` VARCHAR(40),
`previous_reading` INT,
`current_reading` INT,
`amount` INT DEFAULT 0
);
INSERT INTO t (`c_no`, `name`, `previous_reading`,`current_reading`)
VALUES
(101, 'Smith', 90, 120),
(201, 'George', 30, 250),
(301, 'Philip', 120, 200),
(401, 'Jasper', 10,390);
drop procedure if exists p;
DELIMITER $$
CREATE PROCEDURE p()
BEGIN
DECLARE flag INT DEFAULT 0;
DECLARE cno INT;
DECLARE pr, cr, amt, unt DOUBLE;
DECLARE curBill
CURSOR FOR
SELECT c_no, `previous_reading`, `current_reading`
FROM t;
DECLARE CONTINUE HANDLER FOR NOT found SET flag = 1;
OPEN curBill;
calUnit: LOOP
FETCH curBill INTO cno, pr, cr;
IF flag <> 1 THEN
SET unt = cr-pr;
ELSE
LEAVE calUnit;
END IF;
IF (unt <= 100) THEN
SET amt = unt*2;
ELSEIF (unt >= 101 AND unt <= 200) THEN
SET amt = unt*2.5;
ELSEIF (unt > 201 AND unt <= 300) THEN
SET amt = unt*3;
ELSEIF (unt > 301) THEN
SET amt = unt*4;
END IF;
UPDATE t
SET `amount`=amt
where c_no = cno;
END LOOP;
CLOSE curBill;
END $$
DELIMITER ;
CALL p();
SELECT * FROM t;
+------+--------+------------------+-----------------+--------+
| c_no | name | previous_reading | current_reading | amount |
+------+--------+------------------+-----------------+--------+
| 101 | Smith | 90 | 120 | 60 |
| 201 | George | 30 | 250 | 660 |
| 301 | Philip | 120 | 200 | 160 |
| 401 | Jasper | 10 | 390 | 1520 |
+------+--------+------------------+-----------------+--------+
4 rows in set (0.00 sec)