impdp默认不导入GRANT权限,连SELECT授权都会静默跳过;必须导出时显式指定CONTENT=ALL或INCLUDE=GRANT,并提前在目标库创建用户、角色及表空间,否则权限将因依赖缺失而被ORA-39112跳过。

impdp 默认不导入 GRANT,连 SELECT 权限都静默跳过
直接用 impdp 导入用户数据,哪怕加了 SCHEMAS=scott,默认也不会带任何权限。日志里只有一行 ORA-39112: Dependent object type GRANT:"HR" skipped,不报错、不中断,但目标库查表就报 ORA-00942: table or view does not exist——其实是没权限,不是表没导过去。
原因很简单:impdp 的 GRANTS=YES 是默认值,但它只在目标库已存在对应用户、角色、对象的前提下才生效;一旦 hr 用户不存在,所有 GRANT ... TO hr 全部跳过,毫无提示。
- 导出端必须显式加
CONTENT=ALL(最稳妥)或INCLUDE=GRANT -
CONTENT=ALL会导出表、索引、约束、视图、同义词、触发器 + 所有GRANT语句 -
INCLUDE=GRANT只导“被授予方”视角的授权(如GRANT SELECT ON scott.emp TO hr),不导WITH GRANT OPTION链路,也无法还原“谁授的权” - 别信
GRANTS=YES能起作用——它只是开关,不是兜底逻辑
目标库必须提前建好用户、角色、表空间
impdp 不执行 CREATE USER、CREATE ROLE 或 CREATE TABLESPACE。如果目标库没有 hr 用户,那所有授给 hr 的权限都会跳过;如果用了自定义角色 my_app_role,而目标库没建,GRANT my_app_role TO hr 同样失效。
- 先查源库密码哈希:
SELECT username, password FROM dba_users WHERE username = 'HR' - 在目标库执行:
CREATE USER hr IDENTIFIED BY VALUES 'xxx' DEFAULT TABLESPACE users(用查到的password值) - 如有自定义角色,提前运行:
CREATE ROLE my_app_role,并至少赋予CONNECT和RESOURCE - 确保目标库存在对应表空间,且用户有配额:
ALTER USER hr QUOTA UNLIMITED ON users
REMAP_SCHEMA 不改 GRANT 里的 schema 名
加 REMAP_SCHEMA=scott:hr 只影响表、索引等对象的属主,不影响 GRANT 语句中硬编码的 schema 名。比如导出语句是 GRANT SELECT ON scott.emp TO hr,导入时仍按 scott.emp 解析——如果目标库没 scott 用户,或该表不在 scott 下,权限就挂了。
- 要么在导出前确保源库
scott.emp存在且可访问(用于权限校验) - 要么导出时用
SCHEMAS=scott+CONTENT=ALL,导入时用REMAP_SCHEMA=scott:hr,同时确保目标库已建好hr用户和对应表空间 - 不要指望
REMAP_SCHEMA自动重写GRANT中的对象引用
用 DBMS_METADATA 手动生成 GRANT 语句更可控
当需要精确克隆、跳过继承权限、或避免 dump 文件里混杂无效授权时,直接查数据字典生成可执行语句更可靠。Oracle 提供 DBMS_METADATA.GET_GRANTED_DDL,但要注意三类权限来源不同,必须分开处理:
- 系统权限:
SELECT DBMS_METADATA.GET_GRANTED_DDL('SYSTEM_GRANT', 'OLD_USER') FROM DUAL - 对象权限:
SELECT DBMS_METADATA.GET_GRANTED_DDL('OBJECT_GRANT', 'OLD_USER') FROM DUAL - 角色授权:
SELECT DBMS_METADATA.GET_GRANTED_DDL('ROLE_GRANT', 'OLD_USER') FROM DUAL - 对含双引号的对象名(如
"MyTable"),必须保留引号,否则GRANT SELECT ON MyTable TO NEW_USER会失败;可用DBMS_ASSERT.ENQUOTE_NAME安全包裹 - 角色名必须全大写:
GRANT MYAPP_ROLE TO new_user,小写会报错
真正难的不是生成语句,而是判断哪些权限该复制、哪些该过滤——比如跳过 ADMIN_OPTION = 'NO' 的角色、排除 GRANTEE 不是目标用户的间接权限、校验对象是否真实存在。这些细节漏掉,生成的脚本一跑就报错。











