DBMS_METADATA.GET_DDL提取存储过程DDL需先配置SET LONG 100000、SET PAGESIZE 0、SET FEEDBACK OFF等环境参数防截断,并执行SET_TRANSFORM_PARAM禁用STORAGE;查当前用户过程可省略owner,跨schema必须指定大写owner且当前用户需有SELECT_CATALOG_ROLE权限。
DBMS_METADATA.GET_DDL 是提取存储过程 DDL 的标准方式,但直接调用容易返回截断、带 STORAGE 参数或权限缺失的脚本——不是函数本身有问题,而是环境配置和参数组合没对。
执行前必须设好的 SQL*Plus 环境参数
不设这些,dbms_metadata.get_ddl 返回的 clob 很可能被截成几行或只显示开头几十字:
-
SET LONG 100000:CLOB 默认只显示 80 字符,必须扩到足够容纳完整 DDL(小于 10 万会截断复杂过程) -
SET PAGESIZE 0:关掉页头页脚,避免输出里混入“列名”“-----”等干扰行 -
SET FEEDBACK OFF和SET ECHO OFF:防止 “X rows selected” 这类提示污染结果 -
EXECUTE DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'STORAGE', FALSE):否则 DDL 里会带STORAGE (…)、TABLESPACE等与迁移无关的物理属性
查当前用户下的存储过程 DDL
最常用场景:导出自己 schema 里的过程,不用指定 owner:
SELECT DBMS_METADATA.GET_DDL('PROCEDURE', 'MY_PROC') FROM DUAL;
注意:MY_PROC 必须是大写(Oracle 默认对象名存为大写),小写会报 ORA-31603。
如果想批量导出当前用户所有过程:
SELECT DBMS_METADATA.GET_DDL('PROCEDURE', object_name)
FROM USER_OBJECTS
WHERE object_type = 'PROCEDURE';
查其他用户(如 SCOTT)的存储过程 DDL
跨 schema 查询必须显式传入第三个参数(owner):
SELECT DBMS_METADATA.GET_DDL('PROCEDURE', 'GET_EMP_INFO', 'SCOTT') FROM DUAL;
常见错误:
- 漏掉 owner → 报
ORA-31603: object "GET_EMP_INFO" of type PROCEDURE not found in schema "YOUR_SCHEMA" - owner 写小写(如
'scott')→ 函数查不到,因数据字典中 owner 名是大写的 - 当前用户没
SELECT_CATALOG_ROLE或SELECT ANY DICTIONARY权限 → 报ORA-31600: invalid input value或权限拒绝
为什么有时返回空或报 ORA-19206?
DBMS_METADATA.GET_DDL 对某些对象类型(比如包体 PACKAGE BODY)不直接支持,必须换用 'PACKAGE' 类型参数才能拿到完整定义(含包头+包体);而单独查 'PACKAGE BODY' 会失败。
另外,如果过程依赖的对象(如表、类型)在当前 session 不可见,或过程本身编译失败(STATUS = 'INVALID'),GET_DDL 仍会返回 DDL,但内容可能不含完整 body(只返回头声明)。真正要确认是否可执行,得额外查 USER_ERRORS。
最易被忽略的一点:GET_DDL 不处理过程内嵌的动态 SQL 字符串,也不展开引用的 synonym —— 它只忠实还原 DDL 文本,不做语义解析。











