ב 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 >>
נכתב ע"י רם קדם