dbms_metadata.get_ddl是oracle获取对象ddl最直接方式,但需预设set long、pagesize等参数防截断,通过set_transform_param禁用storage/tablespace等冗余项,并确保用户具备select_catalog_role权限及正确指定schema才能成功执行。
dbms_metadata.get_ddl 是 oracle 中获取对象定义(ddl)最直接的方式,但它不是“一查就出可用 sql”的黑盒函数——输出是否干净、是否含 storage/segment 等细节、能否跨 schema 查、是否报权限错误,全取决于会话设置和调用方式。
为什么 SELECT DBMS_METADATA.GET_DDL(...) 返回结果被截断或显示不全
默认 SQL*Plus 或 SQL Developer 的 LONG 和 PAGESIZE 设置极小,GET_DDL 返回的是 CLOB,不显式调整就会只显示前 80 字符或几行。
- 必须在执行前运行:
SET LONG 2000000(建议 ≥2M,避免大表 DDL 被截) -
SET PAGESIZE 0:关闭分页头尾,否则每页插入换行和标题 -
SET TRIMSPOOL ON:防止行末空格被补满,影响 spool 输出 -
SET FEEDBACK OFF和SET ECHO OFF:避免额外文本混入结果
如何过滤掉 storage、tablespace、segment 等物理属性
生产环境导出 DDL 做迁移或比对时,STORAGE、INITIAL、FREELISTS 这类参数往往干扰阅读,且在目标库可能不适用。
- 临时禁用 storage 属性:
EXECUTE DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'STORAGE', FALSE) - 同时去掉段属性:
EXECUTE DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'SEGMENT_ATTRIBUTES', FALSE) - 还原默认行为:
EXECUTE DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'DEFAULT') - 注意:这些是会话级设置,新连接需重设;不设的话,
GET_DDL默认包含全部物理定义
DBMS_METADATA.GET_DDL 支持哪些 object_type 及常见权限陷阱
不是所有对象类型都能无条件查,也不是所有用户都能查任意 schema 的对象。
- 常用
object_type包括:'TABLE'、'VIEW'、'PROCEDURE'、'FUNCTION'、'TRIGGER'、'INDEX'、'SEQUENCE'、'PACKAGE'、'USER'、'TABLESPACE'、'MATERIALIZED VIEW' - 查别人 schema 的对象(如
SCOTT.EMP),当前用户需有SELECT_CATALOG_ROLE或SELECT ANY DICTIONARY权限,否则报ORA-31603: object "EMP" of type TABLE not found in schema "SCOTT" - 查
'USER'或'ROLE'类型时,第三个参数(schema)不能传 NULL,必须明确写用户名,例如:SELECT DBMS_METADATA.GET_DDL('USER', 'SCOTT') FROM DUAL(此时不填 schema 参数会报错) - 查触发器时注意命名冲突:同名触发器可能存在于不同表上,必须指定 owner 和 trigger_name,且确保该 trigger 存在于
DBA_TRIGGERS中可查
批量导出某 schema 下所有表的 DDL 怎么写才安全
直接拼 DBA_TABLES + GET_DDL 容易因权限、对象不存在或 CLOB 拼接失败中断,需加容错和格式控制。
- 不要用
spool直接套整个查询,先确保单条能跑通,再加循环 - 推荐分步:
SET LINESIZE 32767(防行宽截断)、SET LONGCHUNKSIZE 1000000(提升 CLOB 读取效率) - 关键语句示例(仅查当前用户可访问的表):
SELECT 'SELECT DBMS_METADATA.GET_DDL(''TABLE'', ''' || table_name || ''', ''' || owner || ''') FROM DUAL;' FROM all_tables WHERE owner = 'SCOTT'; - 真正批量执行建议改用 PL/SQL 块 +
UTL_FILE写文件,避免 SQL*Plus 缓冲区溢出;若只是临时查看,优先用SELECT ... FROM DBA_OBJECTS WHERE OBJECT_TYPE = 'TABLE'人工挑几个验证
真正麻烦的从来不是语法,而是权限上下文、CLOB 渲染边界、以及那些默认开启却没人告诉你该关的 transform 参数——比如 'CONSTRAINTS_AS_ALTER' 开启后,主键/外键会拆成 ALTER TABLE ADD CONSTRAINT 形式,和建表语句分离,这在做结构一致性校验时容易漏判。











