執行無法解決的編譯錯誤

yangtingkun發表於2009-09-25

如果執行一個過程、函式或者包,或者對檢視執行查詢,Oracle會檢查訪問的物件的狀態,如果物件狀態不正確,則Oracle會嘗試自動編譯物件。

因此絕大部分情況下,可以直接嘗試執行過程,來省略編譯的步驟。但是有的時候,直接執行並不起作用。

 

 

看一個簡單的例子。

在本地的tnsnames.ora中加入下面的配置:

TEST112 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 172.25.198.230)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = test112)
    )
  )

下面建立本地的資料庫鏈,指向遠端的資料庫:

SQL> CREATE DATABASE LINK TEST112
  2  CONNECT TO TEST IDENTIFIED BY TEST
  3  USING 'TEST112';

資料庫連結已建立。

SQL> SELECT * FROM GLOBAL_NAME@TEST112;

GLOBAL_NAME
----------------------------------------------------------------------------
TEST112

建立一個檢視訪問遠端T表,並建立一個過程,在過程中訪問檢視:

SQL> CREATE VIEW V_T112
  2  AS SELECT ID FROM T@TEST112;

檢視已建立。

SQL> CREATE OR REPLACE PROCEDURE P_TEST AS
  2  BEGIN
  3  UPDATE V_T112 SET ID = ID + 1;
  4  END;
  5  /

過程已建立。

SQL> EXEC P_TEST

PL/SQL 過程已成功完成。

下面修改TNSNAMES.ORA裡面TEST112的配置,將配置的名稱改變:

TEST1121 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 172.25.198.230)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = test112)
    )
  )

需要注意,由於DATABASE LINK已經處於開啟的狀態,因此再次訪問並不會報錯,必須手工關閉資料庫,再次訪問遠端物件,Oracle才會利用TNSNAMES.ORA重新解析資料庫鏈:

SQL> EXEC P_TEST

PL/SQL 過程已成功完成。

SQL> ROLLBACK;

回退已完成。

SQL> ALTER SESSION CLOSE DATABASE LINK TEST112;

會話已更改。

SQL> EXEC P_TEST
BEGIN P_TEST; END;

*
1 行出現錯誤:
ORA-12154: TNS:
無法解析指定的連線識別符號
ORA-06512:
"TEST.P_TEST", line 3
ORA-06512:
line 1

檢查過程和檢視的狀態:

SQL> SELECT OBJECT_NAME, STATUS
  2  FROM USER_OBJECTS
  3  WHERE OBJECT_NAME IN ('P_TEST', 'V_T112');

OBJECT_NAME                    STATUS
------------------------------ -------
P_TEST                         VALID
V_T112                         VALID

顯然Oracle並沒有認為執行時的錯誤是由於物件失效造成的。

下面將TNSNAMES.ORA裡面的配置修改回來:

TEST112 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 172.25.198.230)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = test112)
    )
  )

重新執行過程P_TEST

SQL> EXEC P_TEST

PL/SQL 過程已成功完成。

這個現象是正常的,下面再次重複剛才的步驟,將TNSNAMES.ORA中的配置修改為TEST1121,然後執行P_TEST過程:

SQL> EXEC P_TEST

PL/SQL 過程已成功完成。

SQL> ALTER SESSION CLOSE DATABASE LINK TEST112;

會話已更改。

SQL> EXEC P_TEST
BEGIN P_TEST; END;

*
1 行出現錯誤:
ORA-12154: TNS:
無法解析指定的連線識別符號
ORA-06512:
"TEST.P_TEST", line 3
ORA-06512:
line 1

所有的操作都和剛才一樣,現在不一樣的操作出現了,嘗試直接訪問檢視:

SQL> SELECT * FROM V_T112;
SELECT * FROM V_T112
              *
1 行出現錯誤:
ORA-12154: TNS:
無法解析指定的連線識別符號

SQL> ALTER VIEW V_T112 COMPILE;

警告: 更改的檢視帶有編譯錯誤。

SQL> SELECT OBJECT_NAME, STATUS
  2  FROM USER_OBJECTS
  3  WHERE OBJECT_NAME IN ('V_T112', 'P_TEST');

OBJECT_NAME                    STATUS
------------------------------ -------
P_TEST                         INVALID
V_T112                         INVALID

由於檢視的重新編譯,使得檢視和過程的狀態都變成INVALID

下面將TNSNAMES.ORA中的配置修改正確,再次執行P_TEST過程:

SQL> EXEC P_TEST
BEGIN P_TEST; END;

      *
1 行出現錯誤:
ORA-06550:
1 , 7 :
PLS-00905:
物件 TEST.P_TEST 無效
ORA-06550:
1 , 7 :
PL/SQL: Statement ignored

執行仍然報錯,這時手工編譯P_TEST過程也是無效的:

SQL> ALTER PROCEDURE P_TEST COMPILE;

警告: 更改的過程帶有編譯錯誤。

SQL> SHOW ERR
PROCEDURE P_TEST
出現錯誤:

LINE/COL ERROR
-------- -----------------------------------------------------------------
3/1      PL/SQL: SQL Statement ignored
3/8      PL/SQL: ORA-04063: view "TEST.V_T112"
有錯誤

無論是直接執行過程,還是手工編譯過程,都無法解決檢視的問題,這時只能透過手工編譯錯誤的檢視才能解決這個錯誤。

SQL> ALTER VIEW V_T112 COMPILE;

檢視已變更。

SQL> ALTER PROCEDURE P_TEST COMPILE;

過程已更改。

SQL> EXEC P_TEST

PL/SQL 過程已成功完成。

 

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4227/viewspace-615577/,如需轉載,請註明出處,否則將追究法律責任。

相關文章