发表于: 2008.03.22 20:59
分类: ORACLE
出处: http://yangtingkun.itpub.net/post/468/457962
---------------------------------------------------------------
Oracle对于过程会重用OBJECT_ID。这里的过程是指过程、函数、包和对象的总称。
看一个简单的例子:
SQL> CONN YANGTK/YANGTK
SQL> CREATE OR REPLACE PROCEDURE P_TEST AS
2 BEGIN
3 NULL;
4 END;
5 /
过程已创建。
SQL> SELECT OBJECT_ID, OBJECT_NAME FROM DBA_OBJECTS WHERE OBJECT_NAME = 'P_TEST';
OBJECT_ID OBJECT_NAME
---------- ------------------------------
53169 P_TEST
SQL> CREATE OR REPLACE PROCEDURE P_TEST AS
2 BEGIN
3 NULL;
4 END;
5 /
过程已创建。
SQL> SELECT OBJECT_ID, OBJECT_NAME FROM DBA_OBJECTS WHERE OBJECT_NAME = 'P_TEST';
OBJECT_ID OBJECT_NAME
---------- ------------------------------
53169 P_TEST
SQL> DROP PROCEDURE P_TEST;
过程已删除。
SQL> CREATE OR REPLACE PROCEDURE P_TEST AS
2 BEGIN
3 NULL;
4 END;
5 /
过程已创建。
SQL> SELECT OBJECT_ID, OBJECT_NAME FROM DBA_OBJECTS WHERE OBJECT_NAME = 'P_TEST';
OBJECT_ID OBJECT_NAME
---------- ------------------------------
53169 P_TEST
对于CREATE OR REPLACE操作,并不会改变对象的OBJECT_ID,但是对于DROP和CREATE操作来说,Oracle也可以重用原来的OBJECT_ID。
而且这个重用并不需要删除操作和创建操作之间有任何的连续性:
SQL> DROP PROCEDURE P_TEST;
过程已删除。
SQL> CREATE PROCEDURE P_TEST1 AS
2 BEGIN
3 NULL;
4 END;
5 /
过程已创建。
SQL> SELECT OBJECT_ID, OBJECT_NAME FROM DBA_OBJECTS WHERE OBJECT_NAME LIKE 'P_TEST%';
OBJECT_ID OBJECT_NAME
---------- ------------------------------
55490 P_TEST1
SQL> CREATE PROCEDURE P_TEST AS
2 BEGIN
3 NULL;
4 END;
5 /
过程已创建。
SQL> SELECT OBJECT_ID, OBJECT_NAME FROM DBA_OBJECTS WHERE OBJECT_NAME LIKE 'P_TEST%';
OBJECT_ID OBJECT_NAME
---------- ------------------------------
53169 P_TEST
55490 P_TEST1
从上面的结果也可以看出,其实P_TEST过程重用的OBJECT_ID是很早之前产生的,显然这个例子开始时候创建P_TEST的时候,已经是重用OBJECT_ID了。
这说明OBJECT_ID的重用和数据库的会话没有关系。因为这是一个新登陆的会话,执行的过程建立就会重用OBJECT_ID。那么数据库实例的状态是否会影响OBJECT_ID的重用呢:
SQL> DROP PROCEDURE P_TEST;
过程已删除。
SQL> CONN / AS SYSDBA已连接。
SQL> SHUTDOWN IMMEDIATE数据库已经关闭。已经卸载数据库。
ORACLE 例程已经关闭。
SQL> STARTUP
ORACLE 例程已经启动。
Total System Global Area 603979776 bytes
Fixed Size 1249332 bytes
Variable Size 159387596 bytes
Database Buffers 436207616 bytes
Redo Buffers 7135232 bytes数据库装载完毕。数据库已经打开。
SQL> CONN YANGTK/YANGTK已连接。
SQL> CREATE PROCEDURE P_TEST AS
2 BEGIN
3 NULL;
4 END;
5 /
过程已创建。
SQL> SELECT OBJECT_ID, OBJECT_NAME FROM DBA_OBJECTS WHERE OBJECT_NAME LIKE 'P_TEST%';
OBJECT_ID OBJECT_NAME
---------- ------------------------------
55496 P_TEST
55490 P_TEST1
看来OBJECT_ID的重用与Oracle实例中内存里面的某些记录有关。而且,Oracle重用OBJECT_ID似乎只关心名称而不关心过程的内容:
SQL> DROP PROCEDURE P_TEST;
过程已删除。
SQL> CREATE OR REPLACE PROCEDURE P_TEST AS
2 BEGIN
3 DBMS_OUTPUT.PUT_LINE('THIS PROCEDURE IS DIFFERENENT!');
4 END;
5 /
过程已创建。
SQL> SELECT OBJECT_ID, OBJECT_NAME FROM DBA_OBJECTS WHERE OBJECT_NAME = 'P_TEST';
OBJECT_ID OBJECT_NAME
---------- ------------------------------
55496 P_TEST
SQL> DROP PROCEDURE P_TEST;
过程已删除。
SQL> CREATE OR REPLACE FUNCTION P_TEST RETURN NUMBER AS
2 BEGIN
3 RETURN 1;
4 END;
5 /
函数已创建。
SQL> SELECT OBJECT_ID, OBJECT_NAME FROM DBA_OBJECTS WHERE OBJECT_NAME = 'P_TEST';
OBJECT_ID OBJECT_NAME
---------- ------------------------------
55496 P_TEST
SQL> DROP FUNCTION P_TEST;
函数已删除。
SQL> CREATE PACKAGE P_TEST AS
2 PROCEDURE P_ABC;
3 END;
4 /
程序包已创建。
SQL> SELECT OBJECT_ID, OBJECT_NAME FROM DBA_OBJECTS WHERE OBJECT_NAME = 'P_TEST';
OBJECT_ID OBJECT_NAME
---------- ------------------------------
55496 P_TEST
从这个例子以可以看到,Oracle不止不关心前后两次内容是否相同,连是否相同对象都不关心。不管过程、函数还是包,只要名称相同,就可以重用OBJECT_ID。
SQL> DROP PACKAGE P_TEST;
程序包已删除。
SQL> CREATE PROCEDURE USER_A.P_TEST AS
2 BEGIN
3 NULL;
4 END;
5 /
过程已创建。
SQL> SELECT OBJECT_ID, OWNER, OBJECT_NAME FROM DBA_OBJECTS WHERE OBJECT_NAME = 'P_TEST';
OBJECT_ID OWNER OBJECT_NAME
---------- ------------------------------ ------------------------------
55497 USER_A P_TEST
除了名称,过程的OWNER显然也是Oracle关心的对象。
根据上面的特点,推测Oracle在内存中记录了每个用户的每个过程对应的OBJECT_ID,而这个OBJECT_ID的记录并没有随着过程的删除而删掉,因此同名的过程重新创建时,就可以重用这个OBJECT_ID。
OBJECT_ID的重用只对过程、函数和包有效,而表、索引等其他类型的对象没有这个特性。











