DBMS_METADATA.GET_DDL提取存储过程DDL需先配置SET LONG 100000、SET PAGESIZE 0、SET FEEDBACK OFF等环境参数防截断,并执行SET_TRANSFORM_PARAM禁用STORAGE;对象名须大写,跨schema需指定大写owner且当前用户需有SELECT_CATALOG_ROLE权限。

DBMS_METADATA.GET_DDL('PROCEDURE', ...) 返回截断或乱码
直接执行 SELECT DBMS_METADATA.GET_DDL('PROCEDURE','MY_PROC') FROM DUAL 很可能只看到前几十个字符,甚至带换行和分隔线——这不是函数没返回,是 SQL*Plus 默认把 CLOB 当成短文本处理了。
必须提前设置终端输出参数:
-
SET LONG 100000:把 CLOB 显示长度扩到至少 10 万字节(复杂过程含注释、长签名时容易超 8000) -
SET PAGESIZE 0:关掉页眉页脚,否则会混入-----和列名 -
SET FEEDBACK OFF和SET ECHO OFF:避免1 row selected这类干扰行污染结果
DDL 里出现 STORAGE、TABLESPACE 等物理属性
默认导出的 DDL 包含 STORAGE (INITIAL ...)、TABLESPACE USERS 这类与迁移无关的物理配置,导致脚本在目标库执行失败或不一致。
解决方式是禁用这些 transform 参数:
- 执行
EXECUTE DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'STORAGE', FALSE) - 同理可加
'SEGMENT_ATTRIBUTES', FALSE和'CONSTRAINTS_AS_ALTER', FALSE(后者让外键约束单独生成 ALTER 语句) - 注意:这些设置是 session 级的,每次新连接都要重设
查不到存储过程,报 ORA-31603 或 ORA-31600
常见原因不是对象不存在,而是调用姿势不对:
- 对象名写小写 → Oracle 数据字典里存的是大写,
'my_proc'必须写成'MY_PROC' - 跨 schema 查询漏掉 owner →
GET_DDL('PROCEDURE','MY_PROC')只查当前用户;查 SCOTT 的过程必须写GET_DDL('PROCEDURE','MY_PROC','SCOTT'),且 owner 名也得大写 - 权限不足 → 当前用户需有
SELECT_CATALOG_ROLE或SELECT ANY DICTIONARY,否则直接拒绝访问数据字典
批量导出当前用户所有存储过程
用 USER_OBJECTS 视图最稳妥,不用拼接 owner:
SELECT DBMS_METADATA.GET_DDL('PROCEDURE', object_name)
FROM USER_OBJECTS
WHERE object_type = 'PROCEDURE';
如果要导出到文件(如 SQL*Plus 中),建议加 SPOOL procedures.sql 开头和 SPOOL OFF 结尾;注意别忘了前面那套 SET 和 EXECUTE 配置,少一个都可能导出失败。
真正容易被忽略的是:DBMS_METADATA.GET_DDL 对 PACKAGE BODY 类型不支持,查包体必须用 'PACKAGE' 类型参数——这个限制不报错,但返回空,得靠经验判断。


















