今天在论坛上看到一个问题:http://www.itpub.net/335446.html。感觉比较有意思,就测试了一下,下面给出问题的解决步骤。
SQL> CONN YANGTK/YANGTK@YANGTK
已连接。
SQL> CREATE TABLE T (ID NUMBER);
表已创建。
SQL> CONN YANGTK/YANGTK@TEST4
已连接。
SQL> CREATE DATABASE LINK YANGTK.YANGTINGKUN CONNECT TO YANGTK IDENTIFIED BY YANGTK USING 'YANGTK';
数据库链接已创建。
SQL> DESC T@YANGTK
名称 是否为空? 类型
------------------- -------- --------------
ID NUMBER
对于本地的表,只需要调用DBMS_METADATA.GET_DDL就可以直接得到对象的定义。
SQL> SET LONG 1000
SQL> SELECT DBMS_METADATA.GET_DDL('TABLE', 'A') FROM DUAL;
DBMS_METADATA.GET_DDL('TABLE','A')
--------------------------------------------------------------
CREATE TABLE "YANGTK"."A"
( "ID" NUMBER,
"NAME" VARCHAR2(30),
PRIMARY KEY ("ID")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "USERS" ENABLE
) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "USERS"
而对于远端的表,将TABLENAME@DBLINKNAME作为参数传给GET_DDL函数肯定是不行的,因为在本地的数据字典中得不到远端对象的定义。
SQL> SELECT DBMS_METADATA.GET_DDL('TABLE', 'T@YANGTK') FROM DUAL;
ERROR:
ORA-31603: 对象 "T@YANGTK" 属于类型 TABLE, 在方案 "YANGTK" 中未找到
ORA-06512: 在"SYS.DBMS_SYS_ERROR", line 105
ORA-06512: 在"SYS.DBMS_METADATA_INT", line 2857
ORA-06512: 在"SYS.DBMS_METADATA_INT", line 3192
ORA-06512: 在"SYS.DBMS_METADATA_INT", line 4078
ORA-06512: 在"SYS.DBMS_METADATA", line 326
ORA-06512: 在"SYS.DBMS_METADATA", line 410
www.ixdba.net
ORA-06512: 在"SYS.DBMS_METADATA", line 449
ORA-06512: 在"SYS.DBMS_METADATA", line 615
ORA-06512: 在"SYS.DBMS_METADATA", line 1221
ORA-06512: 在line 1
未选定行
因此,必须调用远端的函数来获取远端对象的定义。
SQL> SELECT DBMS_METADATA.GET_DDL@YANGTK('TABLE', 'T') FROM DUAL;
SELECT DBMS_METADATA.GET_DDL@YANGTK('TABLE', 'T') FROM DUAL
*
ERROR 位于第 1 行:
ORA-06553: PLS-564: 在对远程服务器的调用中不允许有大对象参数
此时会报6553错误,由于返回值是CLOB类型,因此出错。下面尝试将CLOB转化为VARCHAR2类型。为了保证不将LOB对象传递回来,DBMS_LOB包的SUBSTR过程也必须是远端调用。
SQL> SELECT DBMS_LOB.SUBSTR@YANGTK(DBMS_METADATA.GET_DDL@YANGTK('TABLE', 'T')) FROM DUAL;
SELECT DBMS_LOB.SUBSTR@YANGTK(DBMS_METADATA.GET_DDL@YANGTK('TABLE', 'T')) FROM DUAL
*
ERROR 位于第 1 行:
ORA-06553: PLS-564: 在对远程服务器的调用中不允许有大对象参数
Oracle仍然要在网络间传递LOB对象,这应该是由于分布式语句造成的。尝试将分布式语句转化为远端语句。
SQL> SELECT DBMS_LOB.SUBSTR@YANGTK(DBMS_METADATA.GET_DDL@YANGTK('TABLE', 'T')) FROM DUAL@YANGTK;
DBMS_LOB.SUBSTR@YANGTK(DBMS_METADATA.GET_DDL@YANGTK('TABLE','T'))