ORA-01919本质是角色或用户对象缺失,需用DBA_ROLES确认存在性:默认大写存储,双引号创建则严格大小写匹配;多租户下注意CONTAINER=ALL,Data Pump不导角色需手动预建。
ORA-01919 报错本质是权限对象缺失,不是语法或连接问题
遇到 ora-01917: user or role 'xxx' does not exist,说明当前语句(比如 grant select on tab to xxx 或 grant xxx to user)中引用的 xxx 既不是已存在用户,也不是已创建角色。它和数据库连得上、密码对不对、表存不存在都无关——oracle 在解析授权语句时直接查 dba_roles 和 dba_users,没匹配到就报这个错。
检查角色是否存在必须用 DBA_ROLES,别查 USER_ROLE_PRIVS
普通用户查不到其他角色定义,USER_ROLE_PRIVS 只显示“当前用户被授予了哪些角色”,不能用来确认角色本身是否存在。正确方式是:
- 用
SYS或具备SELECT_CATALOG_ROLE的账号执行:SELECT role FROM dba_roles WHERE UPPER(role) = UPPER('SCOTT_READONLY_ROLE'); - 注意大小写:Oracle 默认大写存储角色名,但如果你用双引号创建过小写角色(如
CREATE ROLE "scott_reader"),就必须严格匹配大小写,且查询时也得加双引号:SELECT role FROM dba_roles WHERE role = 'scott_reader'; - 不要依赖
SELECT * FROM session_roles—— 它只反映当前会话已启用的角色,不反映系统级定义。
角色脚本路径和执行权限很关键:plustrce.sql 不是万能模板
$ORACLE_HOME/sqlplus/admin/plustrce.sql 只负责创建 PLUSTRACE 角色及配套视图权限,它不处理你自定义的角色。如果你在 Data Pump 导入时报 ORA-01917,是因为 impdp 按 schema 导出时根本不会导出 ROLE 对象(只导 ROLE_GRANT),目标库必须提前手动建好角色。
- 建角色要带
NOT IDENTIFIED(除非你真需要密码验证):CREATE ROLE scott_readonly_role NOT IDENTIFIED;
- 建完立刻授予权限,否则角色空有其名:
GRANT SELECT ON scott.emp TO scott_readonly_role;
- 如果角色名含特殊字符或想小写,必须全程用双引号,且后续所有
GRANT/SET ROLE都得保持一致,否则 Oracle 认为是另一个对象。
常见坑:CONTAINER=ALL、PDB 切换、角色名隐式大写
在 12c+ 多租户环境下,角色默认只在当前 PDB 生效。如果 impdp 进入的是 CDB$ROOT,但角色建在 PDB 中,就会报 ORA-01917。
- 确认当前容器:
SHOW CON_NAME;
- 跨容器建角色需显式指定:
CREATE ROLE c##common_role NOT IDENTIFIED CONTAINER=ALL;
- 即使你在 PDB 里用
CREATE ROLE reader,Oracle 仍存为READER;但若用CREATE ROLE "reader",则严格存为小写,且GRANT "reader" TO scott必须带引号,漏掉就报错。
最易忽略的一点:Data Pump 导入失败后,部分 ROLE_GRANT 语句可能已跳过,但对应的角色对象仍未创建——不能只看日志里哪条报错,得先确保所有被引用的角色都存在于目标库的 DBA_ROLES 中,再重跑导入。











