DBMS_METADATA.GET_DDL需正确配置环境参数才能返回完整、干净的DDL:必须设置SET LONG 100000、PAGESIZE 0、FEEDBACK OFF、ECHO OFF,并调用SET_TRANSFORM_PARAM禁用STORAGE等冗余项,对象名须大写,跨schema需相应权限。

DBMS_METADATA.GET_DDL 直接调用大概率失败或返回截断、带 STORAGE、缺权限的垃圾结果——不是函数不能用,而是没配环境、没设参数、没查权限。
SQL*Plus 环境必须提前设置的四项
不设这些,DBMS_METADATA.GET_DDL 返回的 CLOB 会被截成几行、开头几十字,或者混入页眉页脚、提示信息:
-
SET LONG 100000:默认只显示 80 字符,复杂存储过程或包体直接被砍掉 -
SET PAGESIZE 0:关掉“列名”“------”这类分隔线,否则 DDL 里会夹杂无关字符 -
SET FEEDBACK OFF和SET ECHO OFF:避免 “1 row selected” 或执行语句本身污染输出 -
EXEC DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'STORAGE', FALSE):否则 DDL 里必带STORAGE (…)、TABLESPACE等迁移时根本不需要的物理属性
对象名大小写和 owner 指定规则
Oracle 内部对象名默认存为大写,小写传参直接报 ORA-31603;跨 schema 访问还涉及权限和显式 owner:
- 查当前用户下的
PROCEDURE:SELECT DBMS_METADATA.GET_DDL('PROCEDURE', 'MY_PROC') FROM DUAL——MY_PROC必须大写,不写 owner - 查其他用户(如 SCOTT)的表:
SELECT DBMS_METADATA.GET_DDL('TABLE', 'EMP', 'SCOTT') FROM DUAL—— owner 必须大写,且当前用户需有SELECT_CATALOG_ROLE(不是SELECT ANY DICTIONARY) - 用
ALL_OBJECTS或DBA_OBJECTS查对象是否存在时,同样要大写过滤:SELECT owner, object_name FROM dba_objects WHERE object_name = 'EMP' AND object_type = 'TABLE'
常用 transform 参数组合(禁用冗余项)
只想要干净、可移植的逻辑 DDL,光关 STORAGE 不够,还得顺手关掉其它干扰项:
EXEC DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'TABLESPACE', FALSE)EXEC DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'SEGMENT_ATTRIBUTES', FALSE)-
EXEC DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'CONSTRAINTS', FALSE)—— 如果只要建表语句,不要后续ALTER TABLE ADD CONSTRAINT -
EXEC DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'PRETTY', TRUE)—— 自动换行缩进,提升可读性(非必需但强烈建议) - 所有
SET_TRANSFORM_PARAM是会话级的,每次新连接后都要重设,别指望它自动继承
中文注释/字段名导致 ORA-31011 或乱码
当表含中文注释(COMMENT ON COLUMN)或字段名是中文时,DBMS_METADATA.GET_DDL 容易因字符集转换失败中断:
- 先查会话字符集:
SELECT * FROM nls_session_parameters WHERE parameter IN ('NLS_LANGUAGE', 'NLS_TERRITORY', 'NLS_CHARACTERSET') - 确保客户端
NLS_LANG与数据库NLS_CHARACTERSET一致(如AMERICAN_AMERICA.AL32UTF8) - 临时绕过注释干扰:
EXEC DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'CONSTRAINTS_AS_ALTER', FALSE)(注意不是TRUE) - 如果只是导结构不关心注释,加一句
EXEC DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'SQLTERMINATOR', TRUE)可补上分号,方便粘贴执行
真正容易被忽略的是:所有 SET_TRANSFORM_PARAM 调用都是 session 级、不可跨连接复用的;而 SET LONG 这类 SQL*Plus 设置一旦漏设,输出就不可逆地被截断——你看到的“完整 DDL”,很可能从第 81 个字符开始就没了。


















