איך לפתור את שגיאה ORA-04068

כל אחד שמפתח package-ים ב-PL/SQL נתקל בבעיה הזו לפחות פעם אחת במהלך הפיתוח: ORA-04068: existing state of packages has been discarded. זו בעיה נפוצה למדי בפיתוח package-ים שהפתרון המיידי שלה הוא להריץ שוב את הפרוצדורה או הפונקציה מתוך ה-package כדי שזה יסתדר. בוא נבין מה הבעיה ואיך ניתן לטפל בבעיה.

למה זה קורה בעצם?

כדי להבין את זה נצטרך לחזור רגע אחד להיזכר באחד היתרונות שיש לפקג’ים על פרוצדורות או פונקציות. היתרון שאני מתכוון אליו הוא העובדה שברגע שמריצים פקג’ עם משתנים גלובלים (הן ברמת ה-spec והן ברמת ה-body) הוא נשאר בזיכרון של ה-session וניתן לחזור למשתנים הגלובלים שלו שוב ושוב במהלך אותו ה-session. לתכונה הזו קוראים “שמירת מצב” (או באנגלית state).
כאשר אנחנו מקמפלים את ה-package אנחנו משנים את החתימה של ה-package ובהרצה הבאה אנחנו מקבלים הודעה על כך שה-state שלנו לא תקין יותר ולא ניתן להשתמש בו. בהרצה הבאה אחרי הודעת השגיאה אנחנו יוצרים state חדש וממשיכים הלאה.

כדי להדגים את הבעיה נסתכל על הדוגמה הבאה:

ב-Session 1 נייצר Package:

SQL> create or replace package demo_state is
  2    p number;
  3    procedure demo;
  4  end;
  5  /

Package created.

SQL> l
  1  create or replace package body demo_state is
  2    procedure demo is
  3    begin
  4	 dbms_output.put_line(p);
  5    end;
  6* end;
SQL> /

Package body created.

ב-Session 2 נריץ אותו:

SQL> l
  1  begin
  2	demo_state.p := 1;
  3	demo_state.demo;
  4* end;
SQL> /
1

PL/SQL procedure successfully completed.

עכשיו, אם נשנה ונקמפל את ה-body ב-session 1 אז:

SQL> l
  1  create or replace package body demo_state is
  2    procedure demo is
  3    begin
  4	 dbms_output.put_line(p + 2);
  5    end;
  6* end;
SQL> /

Package body created.

אז ב-session 2 נקבל:

SQL> l
  1  begin
  2	demo_state.p := 1;
  3	demo_state.demo;
  4* end;
SQL> /
begin
*
ERROR at line 1:
ORA-04068: existing state of packages has been discarded
ORA-04061: existing state of package body "ZELKAYAM2.DEMO_STATE" has been
invalidated
ORA-04065: not executed, altered or dropped package body "ZELKAYAM2.DEMO_STATE"
ORA-04061: existing state of package body "ZELKAYAM2.DEMO_STATE" has been
invalidated
ORA-04065: not executed, altered or dropped package body "ZELKAYAM2.DEMO_STATE"
ORA-06508: PL/SQL: could not find program unit being called:
"ZELKAYAM2.DEMO_STATE"
ORA-06512: at line 3

אוקיי – עכשיו הבעיה ברורה אבל רגע, רוב האנשים בכלל לא משתמשים בתכונה הזו – רוב המפתחים של package-ים משתמשים בהם רק בשביל לאגד ביחד פרוצדורות ופונקציות (ולפעמים גם קבועים) ביחד לשימוש חד פעמי. לא אכפת להם אם יש state או אין state.

פתרון אפשרי לבעיה

אם זה אכן המצב, ולא אכפת לנו להתנהל בלי state, נוכל לפתור את הבעיה בכך שנודיע לקומפיילר שהפקג’ שלנו הוא חד פעמי ואנחנו מוותרים מראש על כל שירותי ה-state שהוא מוכן לספק לנו. כדי לבצע את זה, נוסיף הוראת מהדר (pragma) בשם PRAGMA SERIALLY_REUSABLE גם ל-spec וגם ל-body:

SQL> l
  1  create or replace package demo_state is
  2    PRAGMA SERIALLY_REUSABLE;
  3    p number;
  4    procedure demo;
  5* end;
SQL> /
Package created.

SQL> l
  1  create or replace package body demo_state is
  2	PRAGMA SERIALLY_REUSABLE;
  3	procedure demo is
  4	begin
  5	  dbms_output.put_line(p + 2);
  6	end;
  7* end;
SQL> /
Package body created.-

את ב-session 2:

SQL> l
  1  begin
  2	demo_state.p := 1;
  3	demo_state.demo;
  4* end;
SQL> /

PL/SQL procedure successfully completed.

כדאי לשים לב שבגלל שלא נשמר ה-state הפרוצדורה לא מדפיסה דבר מכוון ש-p שקיבל השמה בצורה חיצונית איבד את הערך שלו בין ההרצות של הפקג’. גם אם נשנה עכשיו את הפקג’ זה לא יפגע בהרצות ב-session 2 מכוון שאין state שמזדבל.

כדאי מאוד לשים לב

  • אם משתמשים ב- -bodyless package (כלומר רק הגדרה של spec) אז ניתן עדיין להשתמש ב-pragma. זה טוב אם נרצה לשמור רשימה של קבועים אבל לא יהיה טוב כדי לשמור ערכים המשתנים בזמן session.
  • אם לפקג’ יש body אז ה-pragma חייבת להופיע גם ב-spec וגם ב-body.
  • מכוון שאין state אז משתנים יאותחלו תמיד לערכם המקורי בכל שימוש בפקג’.
  • לא ניתן להשתמש בפקג’ עם ה-pragma ב-trigger-ים או בזמן שליפות sql.

לקריאה נוספת, ניתן להסתכל בתיעוד.

0 תגובות

השאירו תגובה

Want to join the discussion?
Feel free to contribute!

השאר תגובה

This site uses Akismet to reduce spam. Learn how your comment data is processed.