必须分四类调用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 100000 SET PAGESIZE 0 SET FEEDBACK OFF SET TRIMSPOOL ON SET LINESIZE 32767
不设 PAGESIZE 0 会混入页眉页脚;不关 FEEDBACK 会在输出里插 1 row selected,污染脚本;LINESIZE 太小会导致单行被换行截断。
表空间配额和 PROFILE 容易被忽略
GET_GRANTED_DDL 不覆盖这两项,但它们直接影响用户能否建表或密码是否过期:
oracle知识库
oracle知识库下载
下载
-
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'))获取,但仅对非DEFAULTprofile 有效;若用户用的是DEFAULTprofile,得确认目标库的DEFAULTprofile 定义是否一致
另外,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 → 配表空间配额 → 授系统权限 → 授角色 → 设默认角色 → 授对象权限 —— 任何一步缺失或顺序错乱,都可能导致权限行为偏差。