1

I have written a PL/SQL block which needs to perform the following task :

2 tables have been created :

1) Borrower :

+-------------+-------------+------+-----+---------+-------+
| Field       | Type        | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| rollno      | int(11)     | NO   | PRI | NULL    |       |
| name        | varchar(30) | YES  |     | NULL    |       |
| dataofissue | date        | YES  |     | NULL    |       |
| nameofbook  | varchar(20) | YES  |     | NULL    |       |
| status      | varchar(2)  | YES  |     | NULL    |       |
+-------------+-------------+------+-----+---------+-------+

Its content is :

+--------+------+-------------+------------+--------+
| rollno | name | dataofissue | nameofbook | status |
+--------+------+-------------+------------+--------+
|      1 | a    | 2018-09-10  | Ba         | I      |
|      2 | b    | 2018-09-10  | Bb         | I      |
|      3 | c    | 2018-09-01  | Cc         | R      |
|      4 | d    | 2018-08-01  | Dd         | I      |
|      5 | e    | 2018-09-21  | Ee         | I      |
|      6 | f    | 2018-09-18  | Ff         | I      |
+--------+------+-------------+------------+--------+

2) Fine - It has no data. But, its schema is :

+--------+---------+------+-----+---------+-------+
| Field  | Type    | Null | Key | Default | Extra |
+--------+---------+------+-----+---------+-------+
| rollno | int(11) | NO   | PRI | NULL    |       |
| days   | int(11) | NO   |     | NULL    |       |
| amt    | int(11) | NO   |     | NULL    |       |
+--------+---------+------+-----+---------+-------+

Check the no. of days(from date of issue to current date) in Borrower table :

  • if days are between 15 to 30 then fine amounts will be $5/day.
  • If no. of days>30 then fine amount will be $50/day and for days less than 30, $5/day.

Then, the status will change from I to R. Fine will only be calculated for those whose status is I and not R.

  • I indicate book issued.
  • R indicate book returned.

The relevant information will be stored in the Fine table with amt as the total fine imposed and date as the curdate() when the book is returned.

Here, is the procedure that I've written but I'm unable to call the procedure with valid arguments.

mysql> Delimiter //
mysql> Create  procedure proce(in roll int, in bname varchar(20))
    -> Begin
    -> Declare notfound int default 0;
    -> Declare rno int default 0;
    -> Declare name varchar(20);
    -> Declare doi date;
    -> Declare nob varchar(20);
    -> Declare stat varchar(20);
    -> Declare diff int default 0;
    -> Declare fine  int default 0;
    -> Declare cursor_name cursor for select rollno, name, dataofissue, nameofbook, status from borrower;
    -> Declare continue handler for NOT FOUND set notfound=1;
    -> Open cursor_name;
    -> loop_1 : LOOP
    -> fetch cursor_name into rno, name, doi, nob, stat ;
    -> If notfound=1 then
    -> leave loop_1;
    -> end if;
    -> 
    -> If(rno=roll and nob=bname) then
    -> 
    -> Select datediff(curdate(),doi) as DAYS into diff;
    -> if(stat=“I”) then
    -> if(diff >=15  and diff <=30 ) then
    -> set fine=( diff-15 )*5;
    -> elseif( diff > 30 ) then 
    -> set fine=(diff-30)*50 + 15*5;
    -> end if;
    -> insert into fine values(rno,diff,fine);
    -> update borrower set status='D' where rollno=rno; 
    -> end if;
    -> 
    -> 
    -> End if;
    -> 
    -> End LOOP loop_1;
    -> Close cursor_name;
    -> End;//
Query OK, 0 rows affected (0.03 sec)

I call it here:

mysql> call proce(1,"Ba")//

ERROR 1054 (42S22): Unknown column '“I”' in 'field list'

asn
  • 2,408
  • 5
  • 23
  • 37
  • Do you have some trigger on one of the table you use? I had a similar problem with a code that looked right, no idea why I had an error...it was because my procedure updated some data with a trigger and it was my trigger that has an error, so check this maybe if you have some ! – Mickaël Leger Oct 22 '18 at 10:23
  • No, I've not used any trigger. Just for the sake of knowledge, how shall I get to know if I've used one. – asn Oct 22 '18 at 10:26
  • a PL/SQL block - don't think so. – P.Salmon Oct 22 '18 at 10:26
  • `SHOW TRIGGER FROM/IN db_name` : Documentation here : https://dev.mysql.com/doc/refman/8.0/en/show-triggers.html – Mickaël Leger Oct 22 '18 at 10:27
  • `mysql> show triggers// Empty set (0.00 sec)` No trigger there !! – asn Oct 22 '18 at 10:32
  • I cam reproduce your problem with the data provided (and no triggers). And commenting out the insert and update statements doesn't make the error go away. – P.Salmon Oct 22 '18 at 10:48
  • I tried calling the procedure with different parameters which are not in the table `borrower` and it works well - `mysql> call proce(1,"haha")// Query OK, 0 rows affected (0.01 sec)` but not for the parameters which are actually there in the table. Although, nothing is inserted into the table as the condition has not been applied inside the procedure for such parameters. – asn Oct 22 '18 at 10:54
  • Actually its just the odd quotes in this statement if(stat=“I”) - you should just use single quotes for literals. – P.Salmon Oct 22 '18 at 10:57
  • No, I tried it and still throws : `ERROR 1054 (42S22): Unknown column '‘I’' in 'field list'` – asn Oct 22 '18 at 10:59
  • I tried it and it works just fine. – P.Salmon Oct 22 '18 at 11:01
  • Kindly send me the code and I'll just try it to see if the problem presists. – asn Oct 22 '18 at 11:02

1 Answers1

1

The odd quotes in this statement if(stat=“I”) seem to be the problem - change to single quote and the proc works.

drop table if exists borrower,fine; create table Borrower( rollno int(11) , name varchar(30), dataofissue date,
nameofbook varchar(20), status varchar(2)
); insert into borrower values ( 1 , 'a' , '2018-09-10' , 'Ba' , 'I'),
( 2 , 'b' , '2018-09-10' , 'Bb' , 'I'),
( 3 , 'c' , '2018-09-01' , 'Cc' , 'R'),
( 4 , 'd' , '2018-08-01' , 'Dd' , 'I'),
( 5 , 'e' , '2018-09-21' , 'Ee' , 'I'),
( 6 , 'f' , '2018-09-18' , 'Ff' , 'I');

create table fine
( rollno  int(11),
 days    int(11), 
 amt     int(11));

drop procedure if exists proce;
 Delimiter //
 Create  procedure proce(in roll int, in bname varchar(20))
     Begin
     Declare notfound int default 0;
     Declare rno int default 0;
     Declare name varchar(20);
     Declare doi date;
     Declare nob varchar(20);
     Declare stat varchar(20);
     Declare diff int default 0;
     Declare fine  int default 0;
     Declare cursor_name cursor for select rollno, name, dataofissue, nameofbook, status from borrower;
     Declare continue handler for NOT FOUND set notfound=1;
     Open cursor_name;
     loop_1 : LOOP
     fetch cursor_name into rno, name, doi, nob, stat ;
     If notfound=1 then
     leave loop_1;
     end if;

     If(rno=roll and nob=bname) then

     Select datediff(curdate(),doi) as DAYS into diff;

      if(stat='I') then
        if(diff >=15  and diff <=30 ) then
            set fine=( diff-15 )*5;
        elseif( diff > 30 ) then 
        set fine=(diff-30)*50 + 15*5;
        end if;
     insert into fine values(rno,diff,fine);
     update borrower set status='D' where rollno=rno; 
     end if;


     End if;


     End LOOP loop_1;
     Close cursor_name;
     End //

call proce(1,'Ba');

select * from fine;

+--------+------+------+
| rollno | days | amt  |
+--------+------+------+
|      1 |   42 |  675 |
+--------+------+------+
1 row in set (0.00 sec)

I would also check that columns,declared variables and parameters don't have the same name and backtick status.

P.Salmon
  • 17,104
  • 2
  • 12
  • 19
  • Yes, it worked. But, what was the problem during insertion with double quotes ? Also, what is the difference between double quotes and single quotes in MySQL. – asn Oct 22 '18 at 15:03
  • 1
    Please review https://stackoverflow.com/questions/11321491/when-to-use-single-quotes-double-quotes-and-back-ticks-in-mysql/11321508 – P.Salmon Oct 22 '18 at 15:05