唯一可靠方案是四次调用dbms_metadata.get_granted_ddl并手动补全user、profile、tablespace_quota三类基础配置;必须设set long 100000等参数防截断,且角色与表空间需预先创建。

直接用 DBMS_METADATA.GET_GRANTED_DDL 四次调用 + 手动补全三类基础配置,是唯一能保证权限完整、可执行、不漏关键项的方案。别信“一条命令搞定”或“impdp 自动带权限”——实测漏 CREATE SESSION 或默认角色,新用户连都连不上。
必须分四类调用 DBMS_METADATA.GET_GRANTED_DDL
对象权限只是表层,一个能登录、查表、建对象的用户,至少依赖四类显式授予:
-
SYSTEM_GRANT:比如CREATE SESSION、CREATE TABLE,缺它连不上库 -
ROLE_GRANT:比如GRANT CONNECT TO U1,决定能拿到哪些角色包 -
DEFAULT_ROLE:比如ALTER USER U1 DEFAULT ROLE CONNECT,控制连接后哪些角色自动生效(只授角色不设默认,等于白授) -
OBJECT_GRANT:比如GRANT SELECT ON HR.EMP TO U1,才是你常查的表级权限
用户名必须全大写,小写或带引号会返回空 CLOB,不是报错,容易误判为“没权限”。不能只跑一次 OBJECT_GRANT 就停手。
SET LONG 不够大会截断语句,导致脚本执行失败
DBMS_METADATA.GET_GRANTED_DDL 返回的是 CLOB,SQL*Plus 默认 LONG 是 80 字符,而一条含多个权限的 GRANT 语句轻松超 2000 字符。截断后生成的脚本像这样:
GRANT CREATE SESSION TO U1; GRANT CREATE TABLE TO U1; GRANT SELECT ON HR.EMP TO U1; GRANT INSERT ON HR.
执行时报 ORA-00922: missing or invalid option。必须提前设置:
SET LONG 100000 SET PAGESIZE 0 SET FEEDBACK OFF SET TRIMSPOOL ON
不关 FEEDBACK 会混入 1 row selected;不设 PAGESIZE 0 可能插页眉页脚,污染脚本。
还要单独补上 USER、PROFILE 和 TABLESPACE_QUOTA
DBMS_METADATA.GET_GRANTED_DDL 不管用户本身怎么建,也不管资源限制。以下三项必须手动加到脚本开头,且顺序不能错:
- 先
CREATE USER(含IDENTIFIED BY VALUES复用密码哈希,避免重置密码) - 再
ALTER USER ... PROFILE(如果原用户用了非默认 profile) - 然后
ALTER USER ... QUOTA(比如UNLIMITED ON users,否则建表直接报ORA-01536)
漏配额最常见:用户能登录、能查表,但一建表就失败,查半天才发现是表空间 quota 为 0。
导出后别直接执行,先验证第一行是否完整
生成的脚本第一行要是完整的 GRANT,而不是 GRANT SELECT ON ... 后跟省略号或换行乱码。用 head -n 5 script.sql 快速扫一眼。另外注意目标库是否已存在同名角色——GRANT MY_APP_ROLE TO new_user 会失败,如果 MY_APP_ROLE 还没在目标库 CREATE ROLE 过。角色和表空间必须提前建好,impdp 不会帮你建。











