ORA-01917错误源于目标库缺失授权对象(用户或角色),主因是数据泵导入时需复现源库的GRANT语句,但目标环境未创建对应用户FOR_QUERY、角色或其存在于非当前容器;解决需先确认连接容器、检查大小写与引号、区分用户/角色缺失,或使用EXCLUDE=OBJECT_GRANT跳过授权导入。
确认报错用户是否在当前PDB中存在
ora-01917 报错时显示的用户名或角色名,不一定真的“不存在”,而可能是它不在你当前连接的容器(pdb)里。比如你在cdb$root下执行impdp,但目标用户for_query只创建在某个pdb中,那导入过程就会直接报这个错——数据库根本没去那个pdb里找人。
执行以下查询前,先确认你连的是哪个容器:
SELECT SYS_CONTEXT('USERENV', 'CON_NAME') FROM DUAL;如果返回不是目标PDB名(比如是CDB$ROOT),就得切过去:
- SQL*Plus里用
ALTER SESSION SET CONTAINER = pdb_name; - 或者重连:
sqlplus /@pdb_name as sysdba
再查用户是否存在:
SELECT username FROM dba_users WHERE username = 'FOR_QUERY';
注意:dba_users视图在CDB中默认查的是CDB级用户;若FOR_QUERY是PDB本地用户,必须在对应PDB中查才有效。
检查用户名大小写与引号包裹问题
Oracle默认把未加引号的用户名转为大写,但如果你导出时源库用了双引号建了小写或混合大小写的用户(如"myuser"),导入时myuser和"myuser"就是两个不同主体。
常见错误现象:
-
GRANT SELECT ON t TO myuser;报 ORA-01917,但GRANT SELECT ON t TO "myuser";能成功 -
SELECT * FROM dba_users WHERE username = 'myuser';查不到,但SELECT * FROM dba_users WHERE username = 'MYUSER';能查到
解决办法:
- 导出前统一用大写命名用户,避免引号
- 导入报错后,先查
SELECT username FROM dba_users WHERE UPPER(username) = UPPER('for_query'); - 若发现是
"FOR_QUERY"或"For_Query"这类带引号的,建用户时也得加引号:CREATE USER "FOR_QUERY" IDENTIFIED BY pwd;
区分ROLE_GRANT与ROLE对象缺失
ORA-01917 里的名字不一定是普通用户,也可能是角色(ROLE)。而expdp SCHEMA=xxx默认不导出ROLE定义本身,只导出ROLE_GRANT元数据(即“谁被授予了什么角色”)。所以即使源库有SCOTT_READONLY_ROLE,目标库没建它,导入照样失败。
判断方式:
- 看报错SQL里是
TO xxx还是TO ROLE xxx;前者更可能是用户,后者明确指向角色 - 查目标库是否有该角色:
SELECT role FROM dba_roles WHERE role = 'SCOTT_READONLY_ROLE';
修复动作要分两步:
- 若缺失的是角色,先在目标库运行
CREATE ROLE SCOTT_READONLY_ROLE; - 再补上角色所需的权限(不能只靠impdp自动恢复,得手动查源库
dba_role_privs和dba_sys_privs)
特别注意:REMAP_SCHEMA对角色无效,它只映射schema级对象,不处理ROLE或PUBLIC授权。
跳过失败的OBJECT_GRANT而不中断导入
当缺失用户/角色较多,又不想一个个补全时,最务实的办法是让impdp跳过所有失败的授权语句,先确保表、数据、约束等核心对象落地。
关键参数是:
-
EXCLUDE=OBJECT_GRANT:彻底不导入任何授权语句(最干净,但后续要手工补权限) -
TRANSFORM=DISABLE_ARCHIVE_LOGGING:N配合使用可减少日志开销,但不解决ORA-01917 - 慎用
CONTENT=DATA_ONLY:它会跳过元数据,但如果你需要索引、约束等,就不合适
推荐命令组合:
impdp cwy_init2/init@orcl directory=DATA_PUMP_DIR dumpfile=cwy_init_0806.dmp REMAP_SCHEMA=cwy_init1:cwy_init2 EXCLUDE=OBJECT_GRANT logfile=imp_skip_grant.log
导入完成后,再用脚本批量生成目标用户的对象权限——这样既保数据,又留控制权。真正容易被忽略的是:跳过OBJECT_GRANT后,DBA_TAB_PRIVS里不会自动填充任何记录,所有权限都得你手动重建,别误以为“导入完就万事大吉”。


















