Reputation: 35
I have this anonymous block that creates a function and a cursor in the declaration part and uses them :
accept idarticle prompt 'Donner lid article : '
declare
FUNCTION cal_approv(code_art article.idart%type)
RETURN number IS qte_app number;
qtot number;
qtestk number;
qtemin number;
begin
select sum(qte_com) into qtot from lig_com where idart=code_art;
select qtestk into qtestk from article where idart=code_art;
select qtemin into qtemin from article where idart=code_art;
if (qtot/qtestk)>(2*qtemin) then
qte_app := (qtot-qtestk)*1.5;
else
qte_app := qtot*1.2;
end if;
return qte_app;
end;
CURSOR arts is select idart, desart, pu from article where qtestk <= qtemin;
ida number;
da number;
qa number;
pa number;
begin
for art in arts loop
qa := cal_approv(art.idart);
pa := art.pu*cal_approv(art.idart);
exit when(arts%notfound);
insert into resultat values
(art.idart,art.desart, qa,pa);
end loop;
end;
/
select * from resultat;
I tried to create a function on its own in a CREATE OR REPLACE
block, and it worked of me, but I have to delcare it within the declaration block alongside the cursor, so the problem arises with cursor not the function.
Anyhelp is appreciated!
Upvotes: 0
Views: 495
Reputation: 1479
Let me summarize it for you. When you start defining your subprograms you can not declare anything after that. That means when you started defining
FUNCTION cal_approv(code_art article.idart%type)
....
end;
you can not declare anything after that
CURSOR arts is select idart, desart, pu from article where qtestk <= qtemin;
ida number;
da number;
qa number;
pa number;
Just declare variables and cursor before your subprogram.
And as mentioned by @littlefoot, you are using a cursor for loop. Cursor for loop implicitly opens, fetches and closes the records for you. you don't need to write exit condition.
Upvotes: 2
Reputation: 143063
Huh, you declared stuff where you shouldn't, used stuff where you shouldn't, declared variables you never used. I'd suggest you to use a cursor FOR
loop (easier to maintain, you don't have to worry when to exit the loop).
Such a code compiles; see if it helps.
SQL> DECLARE
2 qa NUMBER;
3 pa NUMBER;
4
5 FUNCTION cal_approv(
6 code_art article.idart%TYPE
7 )RETURN NUMBER IS
8 qte_app NUMBER;
9 qtot NUMBER;
10 qtestk NUMBER;
11 qtemin NUMBER;
12 BEGIN
13 SELECT SUM(qte_com)
14 INTO qtot
15 FROM lig_com
16 WHERE idart = code_art;
17
18 SELECT qtestk
19 INTO qtestk
20 FROM article
21 WHERE idart = code_art;
22
23 SELECT qtemin
24 INTO qtemin
25 FROM article
26 WHERE idart = code_art;
27
28 IF(qtot / qtestk)>(2 * qtemin)THEN
29 qte_app :=(qtot - qtestk)* 1.5;
30 ELSE
31 qte_app := qtot * 1.2;
32 END IF;
33
34 RETURN qte_app;
35 END;
36
37 BEGIN
38 FOR art IN(SELECT idart,
39 desart,
40 pu
41 FROM article
42 WHERE qtestk <= qtemin
43 )LOOP
44 qa := cal_approv(art.idart);
45 pa := art.pu * cal_approv(art.idart);
46 INSERT INTO resultat VALUES(
47 art.idart,
48 art.desart,
49 qa,
50 pa
51 );
52 END LOOP;
53 END;
54 /
PL/SQL procedure successfully completed.
SQL>
Declare cursor before the function:
SQL> set serveroutput on
SQL> declare
2 cursor c1 is select * from dept;
3
4 function cal_approv return number is
5 begin
6 return 0;
7 end cal_approv;
8 begin
9 for c1r in c1 loop
10 dbms_output.put_line(c1r.dname ||': function value = ' || cal_approv);
11 end loop;
12 end;
13 /
ACCOUNTING: function value = 0
RESEARCH: function value = 0
SALES: function value = 0
OPERATIONS: function value = 0
PL/SQL procedure successfully completed.
SQL>
If it were vice versa (as you did it):
SQL> declare
2 function cal_approv return number is
3 begin
4 return 0;
5 end cal_approv;
6
7 cursor c1 is select * from dept;
8 begin
9 for c1r in c1 loop
10 dbms_output.put_line(c1r.dname ||': function value = ' || cal_approv);
11 end loop;
12 end;
13 /
cursor c1 is select * from dept;
*
ERROR at line 7:
ORA-06550: line 7, column 3:
PLS-00103: Encountered the symbol "CURSOR" when expecting one of the following:
begin function pragma procedure
SQL>
Upvotes: 1