ב PLSQL כמו בשפות תכנות רבות אחרות, על מנת לפנות לתוכנית מסויימת, יש להצהיר עליה קודם. אם ננסה לקרוא לתוכנית מסויימת עוד לפני שנוצרה – תתקבל שגיאה.
עם זאת, קיימים מקרים בהם הקריאה לתוכנית תהיה קודמת להרצתה, לדוגמא – כאשר נרצה ליישם לוגיקה מסויימת או לייצר מספר תוכניות אשר כל אחת מהן קוראת לשניה.
באמצעות יכולת ה Forward Declaration נוכל להתמודד עם מצבים מסוג זה. כפי שנראה בדוגמאות הבאות, זו מאפשרת להצהיר על תוכניות מראש ולהשתמש בהן עוד לפני שהוגדרו בפועל.
נתחיל עם דוגמא פשוטה – נייצר בלוק אנונימי עם שתי פרוצדרות אשר מבצעות את הפעולות הבאות :
· proc_a – מציגה מלל וקוראת ל proc_b
· proc_bמציגה מלל
וננסה לקרוא לפרוצדורת proc_bמתוך פרוצדורת proc_aעוד לפני שיצרנו אותה.
RAM >> SET SERVEROUTPUT ON
RAM >>
RAM >> -- without forward declaration
RAM >> DECLARE
2 PROCEDURE proc_a
3 IS
4 BEGIN
5 DBMS_OUTPUT.PUT_LINE ('output from procedure A') ;
6 proc_b ;
7 END ;
8
9 PROCEDURE proc_b
10 IS
11 BEGIN
12 DBMS_OUTPUT.PUT_LINE ('output from procedure B') ;
13 END ;
14 BEGIN
15 proc_a ;
16 proc_b ;
17 END ;
18 /
proc_b ;
*
ERROR at line 6:
ORA-06550: line 6, column 2:
PLS-00313: 'PROC_B' not declared in this scope
ORA-06550: line 6, column 2:
PL/SQL: Statement ignored
כפי שניתן לראות, מתקבלת שגיאה מכיוון שבפעם הראשונה בה התבצעה קריאה ל proc_bזו עדיין לא היתה קיימת. במקרים כמו אלו ניתן להשתמש ב Forward Declaration, כאמור, באמצעות יכולת זו ניתן להצהיר על תוכנית מסויימת עוד לפני שנוצרה, לדוגמא –
RAM >> -- using forward declaration
RAM >> DECLARE
2 -- Forward declaration of procedure b
3 PROCEDURE proc_b ;
4
5 PROCEDURE proc_a
6 IS
7 BEGIN
8 DBMS_OUTPUT.PUT_LINE ('output from procedure A') ;
9 proc_b ;
10 END ;
11
12 PROCEDURE proc_b
13 IS
14 BEGIN
15 DBMS_OUTPUT.PUT_LINE ('output from procedure B') ;
16 END ;
17 BEGIN
18 proc_a ;
19 proc_b ;
20 END ;
21 /
output from procedure A
output from procedure B
output from procedure B
PL/SQL procedure successfully completed.
RAM >>
בדוגמא האחרונה יכולנו להמנע מכל הבעיה באמצעות תכנון לוגי שונה – הגדרת פרוצדורת proc_b קודם. אך מה היה קורה אם היו קיימות שתי תוכניות אשר קוראות אחת לשניה ? במקרה זה השימוש ב Forward Declarationיהיה חובה.
לדוגמא – 2 פונקציות אשר מקבלות מספר המהווה שכרומבצעות את הפעולות הבאות :
· above_10k במידה ושכר העובד שווה או מעל 10k הפונקציה תציג את שכרו בתוספת 20% אחרת תתבצע קריאה לפונקצית below_10k
· below_10k במידה ושכר העובד נמוך מ 10k הפונקציה תציג את שכרו בניכוי 20% אחרת תתבצע קריאה לפונקצית above_10k
RAM >> SET SERVEROUTPUT ON
RAM >>
RAM >> DECLARE
2 -- Without Forward Declaration
3 -- FUNCTION below_10k (p_salary number) RETURN number ;
4
5 FUNCTION above_10k
6 (p_salary number)
7 RETURN number
8 AS
9 v_sal number ;
10 BEGIN
11 IF p_salary >>= 10000 THEN
12 v_sal := p_salary * 1.2 ;
13 ELSE
14 v_sal := below_10k(p_salary) ;
15 END IF ;
16 RETURN v_sal ;
17 END ;
18
19
20 FUNCTION below_10k
21 (p_salary number)
22 RETURN number
23 AS
24 v_sal number ;
25 BEGIN
26 IF p_salary < 10000 THEN
27 v_sal := p_salary * 0.8 ;
28 ELSE
29 v_sal := above_10k(p_salary) ;
30 END IF ;
31 RETURN v_sal ;
32 END ;
33
34 BEGIN
35
36 DBMS_OUTPUT.PUT_LINE('Using above_10k function : ') ;
37 DBMS_OUTPUT.PUT_LINE(above_10k(11000)) ;
38 DBMS_OUTPUT.PUT_LINE(above_10k(9000)) ;
39
40
41 DBMS_OUTPUT.PUT_LINE('Using below_10k function : ') ;
42 DBMS_OUTPUT.PUT_LINE(below_10k(11000)) ;
43 DBMS_OUTPUT.PUT_LINE(below_10k(9000)) ;
44
45 END ;
46 /
v_sal := below_10k(p_salary) ;
*
ERROR at line 14:
ORA-06550: line 14, column 12:
PLS-00313: 'BELOW_10K' not declared in this scope
ORA-06550: line 14, column 3:
PL/SQL: Statement ignored
במקרה כמו זה לא תיהיה אפשרות לפתור את הבעיה באמצעות הגדרת תוכנית מסויימת קודם. מקרה זה מחייב Forward Declaration.
RAM >> SET SERVEROUTPUT ON
RAM >>
RAM >> DECLARE
2 -- Using Forward Declaration
3 FUNCTION below_10k (p_salary number) RETURN number ;
4
5 FUNCTION above_10k
6 (p_salary number)
7 RETURN number
8 AS
9 v_sal number ;
10 BEGIN
11 IF p_salary >>= 10000 THEN
12 v_sal := p_salary * 1.2 ;
13 ELSE
14 v_sal := below_10k(p_salary) ;
15 END IF ;
16 RETURN v_sal ;
17 END ;
18
19
20 FUNCTION below_10k
21 (p_salary number)
22 RETURN number
23 AS
24 v_sal number ;
25 BEGIN
26 IF p_salary < 10000 THEN
27 v_sal := p_salary * 0.8 ;
28 ELSE
29 v_sal := above_10k(p_salary) ;
30 END IF ;
31 RETURN v_sal ;
32 END ;
33
34 BEGIN
35
36 DBMS_OUTPUT.PUT_LINE('Using above_10k function : ') ;
37 DBMS_OUTPUT.PUT_LINE(above_10k(11000)) ;
38 DBMS_OUTPUT.PUT_LINE(above_10k(9000)) ;
39
40
41 DBMS_OUTPUT.PUT_LINE('Using below_10k function : ') ;
42 DBMS_OUTPUT.PUT_LINE(below_10k(11000)) ;
43 DBMS_OUTPUT.PUT_LINE(below_10k(9000)) ;
44
45 END ;
46 /
Using above_10k function :
13200
7200
Using below_10k function :
13200
7200
PL/SQL procedure successfully completed.
RAM >>
נקודה אחרונה לגבי Packages – כאשר התוכנית מוגדרת כחלק מה Spec אין צורך ב Forward Declaration ב Body. כאשר התוכנית לא מוגדרת כחלק מה Spec יש צורך ב Forward Declaration ב Body.
RAM >> ------------------------ Forward Declaration is not needed
RAM >>
RAM >>
RAM >>
RAM >>
RAM >> CREATE OR REPLACE PACKAGE my_pack
2 IS
3 FUNCTION above_10k (p_salary number) RETURN number ;
4 FUNCTION below_10k (p_salary number) RETURN number ;
5 END my_pack ;
6 /
Package created.
RAM >>
RAM >> CREATE OR REPLACE PACKAGE BODY my_pack
2 IS
3 FUNCTION above_10k
4 (p_salary number)
5 RETURN number
6 AS
7 v_sal number ;
8 BEGIN
9 IF p_salary >>= 10000 THEN
10 v_sal := p_salary * 1.2 ;
11 ELSE
12 v_sal := below_10k(p_salary) ;
13 END IF ;
14 RETURN v_sal ;
15 END ;
16
17
18 FUNCTION below_10k
19 (p_salary number)
20 RETURN number
21 AS
22 v_sal number ;
23 BEGIN
24 IF p_salary < 10000 THEN
25 v_sal := p_salary * 0.8 ;
26 ELSE
27 v_sal := above_10k(p_salary) ;
28 END IF ;
29 RETURN v_sal ;
30 END ;
31 END my_pack ;
32 /
Package body created.
RAM >>
RAM >> COL COL_1 FOR 99999
RAM >> COL COL_2 FOR 99999
RAM >> COL COL_3 FOR 99999
RAM >> COL COL_4 FOR 99999
RAM >>
RAM >> SELECT my_pack.above_10k(11000) AS COL_1,
2 my_pack.above_10k(9000) AS COL_2,
3 my_pack.below_10k(11000) AS COL_3,
4 my_pack.below_10k(11000) AS COL_4
5 FROM dual ;
COL_1 COL_2 COL_3 COL_4
------ ------ ------ ------
13200 7200 13200 13200
RAM >>
RAM >>
RAM >>
RAM >>
RAM >> ------------------------ Forward Declaration is needed
RAM >>
RAM >>
RAM >>
RAM >>
RAM >>
RAM >> CREATE OR REPLACE PACKAGE my_pack
2 IS
3 FUNCTION above_10k (p_salary number) RETURN number ;
4 END my_pack ;
5 /
Package created.
RAM >>
RAM >> CREATE OR REPLACE PACKAGE BODY my_pack
2 IS
3 FUNCTION above_10k
4 (p_salary number)
5 RETURN number
6 AS
7 v_sal number ;
8 BEGIN
9 IF p_salary >>= 10000 THEN
10 v_sal := p_salary * 1.2 ;
11 ELSE
12 v_sal := below_10k(p_salary) ;
13 END IF ;
14 RETURN v_sal ;
15 END ;
16
17
18 FUNCTION below_10k
19 (p_salary number)
20 RETURN number
21 AS
22 v_sal number ;
23 BEGIN
24 IF p_salary < 10000 THEN
25 v_sal := p_salary * 0.8 ;
26 ELSE
27 v_sal := above_10k(p_salary) ;
28 END IF ;
29 RETURN v_sal ;
30 END ;
31 END my_pack ;
32 /
Warning: Package Body created with compilation errors.
RAM >>
RAM >>
RAM >> SHOW ERROR
Errors for PACKAGE BODY MY_PACK:
LINE/COL ERROR
-------- -----------------------------------------------------------------
12/4 PL/SQL: Statement ignored
12/13 PLS-00313: 'BELOW_10K' not declared in this scope
RAM >>
RAM >>
RAM >>
RAM >>
RAM >> ------------------------ Forward Declaration is needed
RAM >>
RAM >>
RAM >>
RAM >>
RAM >> CREATE OR REPLACE PACKAGE my_pack
2 IS
3 FUNCTION above_10k (p_salary number) RETURN number ;
4 END my_pack ;
5 /
Package created.
RAM >>
RAM >> CREATE OR REPLACE PACKAGE BODY my_pack
2 IS
3
4 -- Using Forward Declaration.
5 FUNCTION below_10k
6 (p_salary number)
7 RETURN number;
8
9 FUNCTION above_10k
10 (p_salary number)
11 RETURN number
12 AS
13 v_sal number ;
14 BEGIN
15 IF p_salary >>= 10000 THEN
16 v_sal := p_salary * 1.2 ;
17 ELSE
18 v_sal := below_10k(p_salary) ;
19 END IF ;
20 RETURN v_sal ;
21 END ;
22
23
24 FUNCTION below_10k
25 (p_salary number)
26 RETURN number
27 AS
28 v_sal number ;
29 BEGIN
30 IF p_salary < 10000 THEN
31 v_sal := p_salary * 0.8 ;
32 ELSE
33 v_sal := above_10k(p_salary) ;
34 END IF ;
35 RETURN v_sal ;
36 END ;
37 END my_pack ;
38 /
Package body created.
RAM >>
RAM >>
RAM >> SELECT my_pack.above_10k(11000) AS COL_1,
2 my_pack.above_10k(9000) AS COL_2
3 FROM dual ;
COL_1 COL_2
------ ------
13200 7200
RAM >>
נכתב ע"י רם קדם