dbms_metadata.get_granted_ddl('object_grant', 'username')可直接生成完整可执行的对象权限语句,自动合并表级与列级权限,但不处理同义词解析;系统、角色、默认角色、表空间配额、profile需分别调用,且用户名须大写、set long需设为100000以防截断。
直接用 dbms_metadata.get_granted_ddl 就能拿到完整、可执行的授权语句,不需要自己拼 sql 或查一堆数据字典视图。
怎么用 GET_GRANTED_DDL 拿到对象权限(比如 GRANT SELECT ON ...)
对象权限包括表、视图、序列等上的 SELECT、INSERT、UPDATE 等,也包含列级授权(如 GRANT UPDATE (col1) ON t TO u)。关键点是:
-
GET_GRANTED_DDL('OBJECT_GRANT', 'USERNAME')会自动合并DBA_TAB_PRIVS和DBA_COL_PRIVS的结果,列级权限也会正确生成带括号的语法 - 如果用户没任何对象权限,函数返回空 CLOB,不是报错 —— 所以执行前最好加
SET LONG 100000并检查输出是否为空 - 注意:该函数不展开同义词(
SYS.ALL_SYNONYMS),如果授权目标是同义词,它会按同义词名输出(如GRANT SELECT ON MY_EMP TO U1),但实际执行时若同义词未解析或指向不存在对象,仍会报ORA-00942
系统权限和角色权限必须分开调用
不能指望一个函数包揽全部。三类权限对应三个独立调用:
- 系统权限:
DBMS_METADATA.GET_GRANTED_DDL('SYSTEM_GRANT', 'U1')→ 输出GRANT CREATE SESSION TO "U1"这类 - 角色权限:
DBMS_METADATA.GET_GRANTED_DDL('ROLE_GRANT', 'U1')→ 输出GRANT "CONNECT" TO "U1",但不递归展开角色内嵌的角色(例如CONNECT包含的CREATE SESSION不会单独列出) - 默认角色:
DBMS_METADATA.GET_GRANTED_DDL('DEFAULT_ROLE', 'U1')→ 只有设为默认的角色才出现,且带ALTER USER ... DEFAULT ROLE ...语句
漏掉其中任意一个,克隆出来的用户就可能无法登录、无法激活角色,或缺少关键能力。
表空间配额和 PROFILE 配置容易被忽略
权限脚本里常缺这两块,导致新用户建表失败或密码策略不一致:
- 表空间配额:
DBMS_METADATA.GET_GRANTED_DDL('TABLESPACE_QUOTA', 'U1')→ 输出ALTER USER "U1" QUOTA UNLIMITED ON "USERS",注意:如果用户在多个表空间有配额,这个函数只返回第一条(rownum = 1是常见陷阱) - PROFILE:
DBMS_METADATA.GET_DDL('PROFILE', p.profile)要配合DBA_USERS查,且只对非DEFAULTprofile 有意义;如果用户用的是DEFAULTprofile,这个调用不返回任何内容,但你得确认目标库的DEFAULTprofile 是否与源库一致
配额和 profile 不是“权限”,但缺失它们会让授权脚本在目标库执行后立即失效 —— 比如 ORA-01950: no privileges on tablespace 'USERS' 就是典型后果。
执行前必须设好 SQL*Plus 环境参数
GET_GRANTED_DDL 返回 CLOB,不设参数会导致截断或乱码:
- 必设:
SET LONG 100000(否则默认只显示 80 字符) - 建议加:
SET PAGESIZE 0、SET TRIMSPOOL ON、SET LINESIZE 32767,避免换行/空格干扰复制 - 别用
SELECT ... FROM DUAL直接贴到生产脚本里 —— 如果某类权限为空,CLOB 为 NULL,整个 UNION ALL 查询可能因空值中断;稳妥做法是分六次单独执行并重定向到文件
最隐蔽的问题是:GET_GRANTED_DDL 对大小写敏感,用户名必须全大写(除非创建时用了双引号),传小写参数会返回空,且无提示。











