必须分四类调用DBMS_METADATA.GET_GRANTED_DDL、用户名全大写、SET LONG≥100000,缺一不可;仅执行OBJECT_GRANT无法复原用户完整权限,因还需SYSTEM_GRANT、ROLE_GRANT、DEFAULT_ROLE三类元信息及TABLESPACE_QUOTA、PROFILE、CREATE USER语句等。
直接用 dbms_metadata 生成可执行脚本是最快路径,但必须分四类调用、用户名全大写、set long 至少设为 100000,漏掉任意一项,导出的脚本大概率无法复原用户行为。
GET_GRANTED_DDL('OBJECT_GRANT', 'U1') 不行对象权限只是用户能力的一小部分。一个能登录、查表、建对象的用户,至少依赖四类元信息:
SYSTEM_GRANT:比如 CREATE SESSION,缺了就根本连不上库ROLE_GRANT:比如 GRANT CONNECT TO "U1",但不展开角色内部权限DEFAULT_ROLE:决定连接后哪些角色自动生效,例如 ALTER USER "U1" DEFAULT ROLE "CONNECT"
OBJECT_GRANT:表/视图/序列上的 SELECT、INSERT 等,含列级授权(如 GRANT UPDATE (name) ON emp TO u1)如果只取 OBJECT_GRANT,新用户可能有表权限,却因没 CREATE SESSION 或没设默认角色而无法执行任何查询。
SET LONG 和输出控制参数必须显式设置DBMS_METADATA.GET_GRANTED_DDL 返回的是 CLOB,SQL*Plus 默认 LONG 值是 80 字符,远不够容纳多条 GRANT 语句。截断后脚本会残缺,执行时报 ORA-00922: missing or invalid option。
必须在执行前一次性设置:
SET LONG 100000SET PAGESIZE 0SET FEEDBACK OFFSET TRIMSPOOL ONSET LINESIZE 32767
不设 PAGESIZE 0 会混入页眉页脚;不关 FEEDBACK 会在输出里插 1 row selected,污染脚本;LINESIZE 太小会导致单行被换行截断。
GET_GRANTED_DDL 不覆盖这两项,但它们直接影响用户能否建表或密码是否过期:
TABLESPACE_QUOTA:用 DBMS_METADATA.GET_GRANTED_DDL('TABLESPACE_QUOTA', 'U1') 获取,注意它只返回第一条配额(rownum = 1 是常见陷阱),若用户在多个表空间有配额,需额外查 DBA_TS_QUOTAS 补全PROFILE:用 DBMS_METADATA.GET_DDL('PROFILE', (SELECT profile FROM dba_users WHERE username = 'U1')) 获取,但仅对非 DEFAULT profile 有效;若用户用的是 DEFAULT profile,得确认目标库的 DEFAULT profile 定义是否一致另外,CREATE USER 语句本身需单独获取:DBMS_METADATA.GET_DDL('USER', 'U1'),它包含密码哈希、默认/临时表空间、账户状态等关键信息。
ORA-00942
GET_GRANTED_DDL('OBJECT_GRANT', 'U1') 遇到通过同义词授予权限时(如 GRANT SELECT ON my_emp TO u1,其中 my_emp 是 scott.emp 的同义词),它原样输出同义词名,不解析为真实对象。脚本执行时若同义词未创建或指向对象不存在,仍报 ORA-00942: table or view does not exist。
更隐蔽的问题是系统对象(如 SYS.DUAL)授权:函数不会校验目标是否存在,只按字面生成 GRANT SELECT ON SYS.DUAL TO "U1"。若目标库未启用 RESTRICTED SESSION 或权限模型不同,这条语句可能失败或被忽略。
真正完整的克隆流程,不是“导出完就完事”,而是必须按顺序执行:建用户 → 设 profile → 配表空间配额 → 授系统权限 → 授角色 → 设默认角色 → 授对象权限 —— 任何一步缺失或顺序错乱,都可能导致权限行为偏差。