I'm new to PL/SQL and Oracle. I'm working on a small code block that generates the top 5 values in a column. I'm trying to get an exception to throw when there are less than 5 rows of data in the table.
DELETE FROM CREDIT_CARD;
SELECT * FROM CREDIT_CARD;
Insert into CREDIT_CARD values (6011956844573649,'550',892);
Insert into CREDIT_CARD values (5250335443644204,'15000',661);
DECLARE
CURSOR Final_Q2_Cursor is
SELECT CREDITCARDNUMBER,CREDITCARDLIMIT,CUSTOMERID FROM CREDIT_CARD
ORDER BY CREDITCARDLIMIT DESC; -- start with highest paid employee
aCardLimt NUMBER(8,2);
aCardNum NUMBER(16);
aCustId INT;
BEGIN
OPEN Final_Q2_Cursor ;
FOR i IN 1..5 LOOP
FETCH Final_Q2_Cursor INTO aCardNum, aCardLimt, aCustId;
EXIT WHEN Final_Q2_Cursor%NOTFOUND;
INSERT INTO TOP_FIVE_CREDIT_LIMITS VALUES (aCardLimt, aCardNum, aCustId);
END LOOP;
CLOSE Final_Q2_Cursor;
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('No such customer!');
WHEN others THEN
dbms_output.put_line('Error!');
END;
/
I only insert 2 rows of data, but it is still processing everything. Why?
Here's an example of where you interrogate the cursor attribute to decide if you need to explicitly raise an error
SQL> create table TOP_FIVE_CREDIT_LIMITS (CREDITCARDLIMIT int, CREDITCARDNUMBER int, CUSTOMERID int );
Table created.
SQL> create table CREDIT_CARD (
2 CREDITCARDNUMBER int,CREDITCARDLIMIT int,CUSTOMERID int );
Table created.
SQL>
SQL> DELETE FROM CREDIT_CARD;
0 rows deleted.
SQL> SELECT * FROM CREDIT_CARD;
no rows selected
SQL> Insert into CREDIT_CARD values (6011956844573649,'550',892);
1 row created.
SQL> Insert into CREDIT_CARD values (5250335443644204,'15000',661);
1 row created.
SQL>
Pl/SQL:
SQL> set serverout on
SQL> DECLARE
2 CURSOR Final_Q2_Cursor is
3 SELECT CREDITCARDNUMBER,CREDITCARDLIMIT,CUSTOMERID FROM CREDIT_CARD
4 ORDER BY CREDITCARDLIMIT DESC; -- start with highest paid employee
5
6 aCardLimt NUMBER(8,2);
7 aCardNum NUMBER(16);
8 aCustId INT;
9 BEGIN
10 OPEN Final_Q2_Cursor ;
11 FOR i IN 1..5 LOOP
12 FETCH Final_Q2_Cursor INTO aCardNum, aCardLimt, aCustId;
13
14 if Final_Q2_Cursor%NOTFOUND and i < 5 then
15 raise_application_error(-20000,'Ran out of rows before I got to 5');
16 end if;
17 EXIT WHEN Final_Q2_Cursor%NOTFOUND;
18 INSERT INTO TOP_FIVE_CREDIT_LIMITS VALUES (aCardLimt, aCardNum, aCustId);
19 END LOOP;
20 CLOSE Final_Q2_Cursor;
21 EXCEPTION
22 WHEN no_data_found THEN
23 dbms_output.put_line('No such customer!');
24 WHEN others THEN
25 dbms_output.put_line('Error!');
26 END;
27 /
Error!
PL/SQL procedure successfully completed.
but I stress, that's not a smart way of doing things (although if its your assignment..then fine). Generally we try keep the code nice and lean by using SQL where possible, and we never like to catch all errors in when-others without propagating them back to the calling environment. So you could also recast your code like follows:
SQL> set serverout on
SQL> BEGIN
2 insert into TOP_FIVE_CREDIT_LIMITS
3 select *
4 from
5 ( SELECT CREDITCARDNUMBER,CREDITCARDLIMIT,CUSTOMERID FROM CREDIT_CARD
6 ORDER BY CREDITCARDLIMIT DESC
7 )
8 where rownum <= 5;
9
10 if sql%rowcount = 0 then
11 raise_application_error(-20000,'No rows were found at all');
12 elsif sql%rowcount < 5 then
13 raise_application_error(-20000,'Ran out of rows before I got to 5');
14 end if;
15
16 END;
17 /
BEGIN
*
ERROR at line 1:
ORA-20000: Ran out of rows before I got to 5
ORA-06512: at line 13
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.