MySQL хранимые процедуры с ошибкой подачи курсора - PullRequest
0 голосов
/ 03 ноября 2019

Я пытаюсь вычислить сумму на основе единицы тока, используемой путем вычитания текущего чтения из предыдущего чтения, но у меня, похоже, есть некоторая синтаксическая ошибка и логическая проблема. Пожалуйста, помогите.

(я знаю, что это можно сделать в самом операторе вставки, но мне нужно понять, как работают курсоры)

ОШИБКА 1064 (42000) в строке 22 файла:'DEF.sql': у вас ошибка в синтаксисе SQL;проверьте руководство, соответствующее вашей версии сервера MariaDB, чтобы узнать правильный синтаксис для использования рядом с '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;

1 Ответ

0 голосов
/ 03 ноября 2019

Множество ошибок synatx, и если вы не используете выражение 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)
...