简单描述执行远端的DBMS_LOB包的一些问题。
由于LOB的定位符无法跨数据库链使用,因此访问远端LOB对象的时候,需要调用远端的DBMS_LOB包中的过程,但是测试发现,即使调用远端的DBMS_LOB包中的过程,仍然可能出现问题。
SQL> CREATE TABLE T_LOB (ID NUMBER, CONTENTS CLOB);
表已创建。
SQL> DECLARE
2 V_LOB CLOB;
3 BEGIN
4 INSERT INTO T_LOB
5 VALUES (1, EMPTY_CLOB())
6 RETURN CONTENTS INTO V_LOB;
7 FOR I IN 1..100 LOOP
8 DBMS_LOB.WRITEAPPEND(V_LOB, 32767, LPAD('A', 32767, 'A'));
9 END LOOP;
10 END;
11 /
PL/SQL过程已成功完成。
SQL> COMMIT;
提交完成。
SQL> SELECT DBMS_LOB.GETLENGTH(CONTENTS) FROM T_LOB;
DBMS_LOB.GETLENGTH(CONTENTS)
----------------------------
3276700
SQL> SELECT * FROM V$VERSION;
BANNER
----------------------------------------------------------------
Oracle Database10gEnterpriseEdition Release10.2.0.3.0 - 64bi
PL/SQL Release 10.2.0.3.0 - Production
CORE 10.2.0.3.0 Production
TNS for Linux: Version 10.2.0.3.0 - Production
NLSRTL Version 10.2.0.3.0 - Production
SQL> SELECT * FROM GLOBAL_NAME;
GLOBAL_NAME
----------------------------------------------------------------------------
TESTZJ
如果在远端数据库中,通过数据库链获取这个LOB字段的长度,直接通过DBMS_LOB.GETLENGTH肯定是行不通的:
SQL> SELECT * FROM GLOBAL_NAME;
GLOBAL_NAME
----------------------------------------------------------------------------------
TEST08
SQL> SELECT * FROM V$VERSION;
BANNER
----------------------------------------------------------------
Oracle Database10gEnterpriseEdition Release10.2.0.3.0 - 64bi
PL/SQL Release 10.2.0.3.0 - Production
CORE 10.2.0.3.0 Production
TNS for Linux: Version 10.2.0.3.0 - Production
NLSRTL Version 10.2.0.3.0 - Production
SQL> CREATE DATABASE LINK TESTZJ
2 CONNECT TO TEST
3 IDENTIFIED BY TEST
4 USING '172.25.13.231/TESTZJ';
Database link created.
SQL> SELECT COUNT(*) FROM T_LOB@TESTZJ;
COUNT(*)
----------
1
SQL> SELECT DBMS_LOB.GETLENGTH(CONTENTS) FROM T_LOB@TESTZJ;
SELECT DBMS_LOB.GETLENGTH(CONTENTS) FROM T_LOB@TESTZJ
*
ERROR at line 1:
ORA-22992: cannot use LOB locators selected from remote tables
尝试调用远端的DBMS_LOB包,但是仍然会导致错误的产生:
SQL> SELECT DBMS_LOB.GETLENGTH@TESTZJ(CONTENTS) FROM T_LOB@TESTZJ;
SELECT DBMS_LOB.GETLENGTH@TESTZJ(CONTENTS) FROM T_LOB@TESTZJ
*
ERROR at line 1:
ORA-22992: cannot use LOB locators selected from remote tables
按道理来说,虽然T_LOB是远端对象,但是DBMS_LOB调用的也是远端过程,LOB定位符的使用并没有跨越数据库,因此应该是可以得到结果的。
在11.2中,Oracle已经可以利用这种方法来进行访问了:
SQL> SELECT * FROM GLOBAL_NAME;
GLOBAL_NAME
---------------------------------------------------------------------------------
TEST112
SQL> SELECT * FROM V$VERSION;
BANNER
--------------------------------------------------------------------------------
Oracle Database11gEnterprise Edition Release11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
SQL> CREATE DATABASE LINK TESTZJ
2 CONNECT TO TEST
3 IDENTIFIED BY TEST
4 USING '172.25.13.231/TESTZJ';
数据库链接已创建。
SQL> SELECT COUNT(*) FROM T_LOB@TESTZJ;
COUNT(*)
----------
1
SQL> SELECT DBMS_LOB.GETLENGTH@TESTZJ(CONTENTS) FROM T_LOB@TESTZJ;
DBMS_LOB.GETLENGTH@TESTZJ(CONTENTS)
-----------------------------------
3276700
SQL> SELECT LENGTH(CONTENTS) FROM T_LOB@TESTZJ;
LENGTH(CONTENTS)
----------------
3276700
在11g中,甚至可以通过LENGTH函数直接获取远端LOB的长度。
虽然10.2中不能通过远端的DBMS_LOB直接访问表中的LOB,但是还是可以利用这个包处理函数返回的LOB。
对于低版本的情况,为了可以使用远端的DBMS_LOB包,需要在远端站点建立一个函数,返回LOB对象:
SQL> SELECT * FROM GLOBAL_NAME;
GLOBAL_NAME
---------------------------------------------------------------------------------
TESTZJ
SQL> CREATE OR REPLACE FUNCTION F_LOB (P_ID IN NUMBER)
2 RETURN CLOB AS
3 V_LOB CLOB;
4 BEGIN
5 SELECT CONTENTS
6 INTO V_LOB
7 FROM T_LOB
8 WHERE ID = P_ID;
9 RETURN V_LOB;
10 END;
11 /
函数已创建。
下面通过调用F_LOB来处理LOB的长度:
SQL> SELECT * FROM GLOBAL_NAME;
GLOBAL_NAME
-------------------------------------------------------------------------
TEST08
SQL> SELECT DBMS_LOB.GETLENGTH@TESTZJ(F_LOB@TESTZJ(1)) FROM T_LOB@TESTZJ;
DBMS_LOB.GETLENGTH@TESTZJ(F_LOB@TESTZJ(1))
------------------------------------------
3276700
SQL> SELECT LENGTH(F_LOB@TESTZJ(1)) FROM T_LOB@TESTZJ;
LENGTH(F_LOB@TESTZJ(1))
-----------------------
3276700
通过在远端先调用F_LOB返回CLOB后,就可以通过远端的DBMS_LOB.GETLENGTH来获取长度了。
在调用远端F_LOB并返回CLOB后,甚至可以直接通过LENGTH来获取LOB字段的长度。
从这一点上看,LENGTH和DBMS_LOB.GETLENGTH要拥有更多的优势。
oracle视频教程请关注:http://u.youku.com/user_video/id_UMzAzMjkxMjE2.html