日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【好文共分享】关于ora-04065和ora-04068的原理解释

發(fā)布時間:2025/5/22 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【好文共分享】关于ora-04065和ora-04068的原理解释 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

轉自:http://tech.it168.com/oldarticle/2006-05-26/200605252326345.shtml

?

今天在運行一個過程是報了一個ORA-4068錯誤。雖然問題很簡單,而且也很容易解決,但是要真正理解的錯誤產生的原因,還需要對概念理解的比較清晰。
?
下面做一個簡單的例子重現(xiàn)錯誤:

SQL> CREATE TABLE T AS SELECT * FROM TAB;
?表已創(chuàng)建。
SQL> CREATE OR REPLACE PROCEDURE P_RECREATE AS
2 BEGIN
3 EXECUTE IMMEDIATE 'DROP TABLE T';
4 EXECUTE IMMEDIATE 'CREATE TABLE T AS SELECT * FROM TAB';
5 END;
6 /
?過程已創(chuàng)建。

SQL> CREATE OR REPLACE PROCEDURE P_INSERT_T AS
2 BEGIN
3 INSERT INTO T SELECT * FROM T;
4 END;
5 /
?過程已創(chuàng)建。
SQL> BEGIN
2 P_RECREATE;
3 P_INSERT_T;
4 END;
5 /
?BEGIN
?*第 1 行出現(xiàn)錯誤:
?ORA-04068: 已丟棄程序包 的當前狀態(tài)
?ORA-04065: 未執(zhí)行, 已更改或刪除 stored procedure "YANGTK.P_INSERT_T"
?ORA-06508: PL/SQL: 無法找到正在調用 : "YANGTK.P_INSERT_T" 的程序單元
?ORA-06512: 在 line 3

如果單獨執(zhí)行兩個過程,則不會報錯:

SQL> EXEC P_RECREATE PL/SQL 過程已成功完成。 SQL> EXEC P_INSERT_T PL/SQL 過程已成功完成。

看到ORA-04068錯誤,我首先想到的是由于在P_RECREATE過程中,對表進行了刪除重建工作,導致和這個表相關的存儲過程變?yōu)镮NVALID。

于是,我嘗試在調用過程之前重編譯P_INSERT_T過程:

SQL> BEGIN
2 P_RECREATE;
3 EXECUTE IMMEDIATE 'ALTER PROCEDURE P_INSERT_T COMPILE';
4 P_INSERT_T;
5 END;
6 /
?BEGIN
?*第 1 行出現(xiàn)錯誤:
?ORA-04068: 已丟棄程序包 的當前狀態(tài)
?ORA-04065: 未執(zhí)行, 已更改或刪除 stored procedure "YANGTK.P_INSERT_T"
?ORA-06508: PL/SQL: 無法找到正在調用 : "YANGTK.P_INSERT_T" 的程序單元
?ORA-06512: 在 line 4

但是發(fā)現(xiàn),錯誤依舊。

SQL> BEGIN
2 P_RECREATE;
3 EXECUTE IMMEDIATE 'BEGIN P_INSERT_T; END;';
4 END;
5 /
?PL/SQL 過程已成功完成。

但如果使用動態(tài)SQL的方式調用P_INSERT_T過程,則不會報錯。

問題已經基本上清楚了,但是要想說明白,還需要從頭說起。

存儲過程在編譯時,自動檢查語法錯誤、權限以及所有對象依賴性等。等到執(zhí)行的時候,Oracle不會再進行類似的檢查,而是直接運行過程,這也是存儲過程擁有較高效率的一個原因。

當存儲過程依賴的對象發(fā)生變化了,Oralce會自動將存儲過程的狀態(tài)置為INVALID,而存儲過程的狀態(tài)如果為INVALID,則會在下次執(zhí)行的時候嘗試重新編譯,如果編譯通過,則繼續(xù)執(zhí)行,編譯失敗則報錯。
這就是為什么兩個過程單獨執(zhí)行時不會報錯。

那么,為什么兩個過程放到一起執(zhí)行就會報錯,即使嘗試重新編譯也無效呢。這是由于導致過程P_INSERT_T失效的過程就在調用P_INSERT_T過程的匿名塊中。在將匿名塊提交給Oracle時,Oracle對里面每個過程的狀態(tài)進行了檢查,由于導致P_INSERT_T失效的P_RECREATE過程還沒有執(zhí)行,這時候,所有過程的狀態(tài)都是VALID,于是Oracle記錄下來過程的信息準備到直接運行。但是調用P_RECREATE過程后,由于T表被刪除重建,P_INSERT_T的狀態(tài)發(fā)生變化,但是Oracle對過程P_INSERT_T的檢查已經完成,因此在嘗試直接運行P_INSERT_T的代碼的時候發(fā)現(xiàn)P_INSERT_T的狀態(tài)已經發(fā)生變化,因此,這里報錯ORA-04068,同樣的道理,即使對P_INSERT_T進行了重新編譯,Oracle在執(zhí)行時發(fā)現(xiàn)檢查時的代碼已經發(fā)生了變化,仍然會報錯,即使這個時候存儲過程的狀態(tài)已經時VALID了。

而采用動態(tài)SQL不會報錯的原因就更容易理解了,由于采用動態(tài)SQL,Oracle將編譯是進行的操作推遲到運行時進行,也就是說,Oracle會在調用P_RECREATE 之后,調用P_INSERT_T過程之前對P_INSERT_T進行檢查并重新編譯,因此,采用動態(tài)SQL不會報錯。

總結

以上是生活随笔為你收集整理的【好文共分享】关于ora-04065和ora-04068的原理解释的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。