如何通过DBLINK取REMOTE DB的DDL

来源:互联网 发布:2016年8月进出口数据 编辑:程序博客网 时间:2024/05/16 18:17

今天在写一个数据库结构同步小工具,需要用到dbms_metadata.get_ddl这个包取对象的DDL。这个包取本地对象的DDL是没有问题的,但在这个工具中,需要通过DBLINK方式取远端数据库的DDL,经过一番资料查找,找到了解决方法。


首先尝试直接在dual用dblink,结果出错:


SQL> SELECT (DBMS_METADATA.GET_DDL('TABLE', 'NEW_A', 'ADMIN')) FROM DUAL@DB230;

SELECT (DBMS_METADATA.GET_DDL('TABLE', 'NEW_A', 'ADMIN')) FROM DUAL@DB230

ORA-31603: object "NEW_A" of type TABLE not found in schema "ADMIN"
ORA-06512: at "SYS.DBMS_METADATA", line 1548
ORA-06512: at "SYS.DBMS_METADATA", line 1585
ORA-06512: at "SYS.DBMS_METADATA", line 1902
ORA-06512: at "SYS.DBMS_METADATA", line 2793
ORA-06512: at "SYS.DBMS_METADATA", line 4333
ORA-06512: at line 1

ADMIN.NEW_A在DB230是存在的,从这个错误可以看出,直接在dual表加dblink是没有意义的,dbms_metadata还是会从本地数据库查看表是否存在。

接着修改一下SQL,在dbms_metadata也加上dblink,看看结果如何:

SQL> SELECT DBMS_METADATA.GET_DDL@DB230('TABLE', 'NEW_A', 'ADMIN') FROM DUAL@DB230;

SELECT DBMS_METADATA.GET_DDL@DB230('TABLE', 'NEW_A', 'ADMIN') FROM DUAL@DB230

ORA-22992: cannot use LOB locators selected from remote tables

现在错误变了,说明在dbms_metadata上加dblink奏效了。新的错误很明显,在SQL方式下,不能直接通过dblink传送lob,所以需要想办法把lob转换为其他类型再传送:

SQL> SELECT DBMS_LOB.SUBSTR@DB230(DBMS_METADATA.GET_DDL@DB230('TABLE', 'NEW_A', 'ADMIN')) FROM DUAL@DB230;

DBMS_LOB.SUBSTR@DB230(DBMS_MET
--------------------------------------------------------------------------------

CREATE TABLE "ADMIN"."NEW_A"
( "TABLE_NAME" VARCHAR2(32),

"D" DATE,

"BYTES" NUMBER

) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
STORAGE(INITIAL 81920 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "ADMIN_TS"

可以看到,此时远端数据库的DDL已经被成功取过来。注意dbms_lob也要加上dblink,表名在远端数据库执行这个函数。

最后简单总结一下:

1.函数和表都可以加dblink,函数加上dblink表示在远端数据库执行该函数,表加上dblink表示从远端数据库读取表。

2. 从远端数据库取DDL,所有函数及表(dbms_metadata/dbms_lob/dual)都要加上dblink,否则会失败

3. 此种方法最多返回32767个字节,如果对象的DDL长度大于32767,则只能部分返回。在处理里需特别处理(如分段取DDL)。

4. 如果是在PL/SQL中取远端数据库对象的DDL,则可以不用dbms_lob,通过变量赋值的方式不需要dbms_lob截断,如:

BEGIN
SELECT DBMS_METADATA.GET_DDL@DB230('TABLE','NEW_A','ADMIN') into V FROM DUAL@DB230;
END;

原创粉丝点击