MySQL存储过程,光标给出错误

MySQL存储过程,光标给出错误,mysql,stored-procedures,mariadb,database-cursor,Mysql,Stored Procedures,Mariadb,Database Cursor,我试图通过从以前的读数中减去当前读数来计算电流单位,但我似乎有一些语法错误和逻辑问题。请帮忙 (我知道可以在insert语句本身中完成,但我需要了解游标是如何工作的) 文件“DEF.sql”中第22行出现错误1064(42000):您的sql语法有错误;检查与您的MariaDB服务器版本相对应的手册,以了解使用near“LOOP: FETCH curBill INTO cno, pr, cr; IF !flag THEN SET unt = cr-pr;

我试图通过从以前的读数中减去当前读数来计算电流单位,但我似乎有一些语法错误和逻辑问题。请帮忙

(我知道可以在insert语句本身中完成,但我需要了解游标是如何工作的)

文件“DEF.sql”中第22行出现错误1064(42000):您的sql语法有错误;检查与您的MariaDB服务器版本相对应的手册,以了解使用near“LOOP:

FETCH curBill INTO cno, pr, cr;
        IF !flag THEN
            SET unt = cr-pr;
        EL' at line 13
MariaDB v10.4.8

随机创建数据库;
随机使用;
创建表客户(
`c_no`INT,
`名字`瓦查尔(40),
`前一个字母为'INT,
`当前读数为'INT,
`amount`INT默认值为0
);
插入客户(`c\U no`、`name`、`previous\U reading`、`current\U reading`)
价值观
(101,“史密斯”,90120),
(201,'乔治',30250),
(301,'Philip',120200),
(401,“贾斯珀”,10390年);
从客户中选择*;
分隔符$$;
创建程序e_bills()
开始
声明标志INT默认为0;
声明cno INT;
申报pr、cr、amt、unt双倍;
宣布科比尔
光标
选择'c\U id','previous\U reading','current\U reading'`
来自客户;
声明未找到集合标志的继续处理程序=1;
开放式路缘石;
calUnit循环:
将科比尔纳入cno、pr、cr;
如果!那么旗帜
设置unt=cr-pr;
否则,如果旗子那么
离开calUnit;
如果结束;
如果(unt=101、unt 201和unt 301),则
设置金额=unt*4;
如果结束;
更新客户
设置“金额”=金额;
端环;
近路缘石;
结束$$
定界符$$
称为e_bills();
从客户中选择*;
随机丢弃数据库;

大量synatx错误,如果在update语句中不使用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)
删除表格(如果存在);
创建表t(
`c_no`INT,
`名字`瓦查尔(40),
`前一个字母为'INT,
`当前读数为'INT,
`amount`INT默认值为0
);
插入到t中(`c_no`、`name`、`previous_reading`、`current_reading`)
价值观
(101,“史密斯”,90120),
(201,'乔治',30250),
(301,'Philip',120200),
(401,“贾斯珀”,10390年);
如果存在p,则删除程序;
分隔符$$
创建过程p()
开始
声明标志INT默认为0;
声明cno INT;
申报pr、cr、amt、unt双倍;
宣布科比尔
光标
选择c_编号、‘上一个_读数’、‘当前_读数’`
从t;
声明未找到集合标志的继续处理程序=1;
开放式路缘石;
计算单位:循环
将科比尔纳入cno、pr、cr;
如果标志1,则
设置unt=cr-pr;
其他的
离开calUnit;
如果结束;
如果(unt=101、unt 201和unt 301),则
设置金额=unt*4;
如果结束;
更新t
设置“金额”=金额
其中c_no=cno;
端环;
近路缘石;
结束$$
定界符;
调用p();
从t中选择*;
+------+--------+------------------+-----------------+--------+
|c|U编号|名称|先前读数|当前读数|金额|
+------+--------+------------------+-----------------+--------+
|101 |史密斯| 90 | 120 | 60|
|201 |乔治| 30 | 250 | 660|
|301 |菲利普| 120 | 200 | 160|
|401 |贾斯珀| 10 | 390 | 1520|
+------+--------+------------------+-----------------+--------+
一组4行(0.00秒)

elseif not else,如果您可以将其归结为一条多表更新语句。没有光标。