简单描述执行远端的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