ORA-65096错误源于Oracle 12c多租户架构下CDB$ROOT中创建用户时强制要求公共用户名以c##或C##开头,且需显式指定CONTAINER=ALL;若需普通用户应先切换至目标PDB再执行CREATE USER。
ora-65096 错误本质是 oracle 强制要求公共用户(在 cdb 环境下)用户名必须以 c## 或 c## 开头,不能绕过,但可以合理适配。
为什么创建用户时突然报 ORA-65096:invalid common user or role name
Oracle 12c 引入多租户(CDB/PDB)后,CREATE USER 在 CDB$ROOT 中执行时,默认按“公共用户”处理。只要没显式指定容器上下文,且用户名不满足 c## 前缀规则,就会触发该错误。这不是 bug,是强制安全策略——防止跨 PDB 的用户命名冲突。
常见错误现象:
- 在 SQL*Plus 或 SQL Developer 连到
CDB$ROOT后直接运行CREATE USER app_user IDENTIFIED BY pwd;→ 立即报ORA-65096 - 误以为加了
CONTAINER=ALL就能用任意名,其实前缀检查仍生效 - 试图用双引号包裹用户名(如
"app_user")逃避校验 → 无效,Oracle 会直接拒绝解析
在 CDB$ROOT 中创建真正公共用户的正确写法
如果确实需要跨所有 PDB 生效的用户(比如运维监控账号),必须接受前缀约束,并显式控制作用域:
- 用户名必须以
c##开头,大小写敏感,C##也合法,但建议统一小写 - 必须加上
CONTAINER = ALL,否则默认仍是CONTAINER=CURRENT(只在当前容器生效) - 密码策略、表空间等参数与其他用户无异,但默认无法直接登录 PDB,需额外授权
示例:CREATE USER c##admin IDENTIFIED BY oracle123 CONTAINER = ALL;
注意:CONTAINER=ALL 不代表自动赋予各 PDB 中的权限,后续需在每个 PDB 中单独执行 GRANT CONNECT, RESOURCE TO c##admin;
想在单个 PDB 里建普通用户?先切容器
绝大多数应用用户根本不需要跨 PDB,此时 ORA-65096 的出现,往往是因为连错了容器。解决方案不是改用户名,而是切换上下文:
- 确认当前连接的是目标 PDB:执行
SHOW CON_NAME,输出应为类似PDB1,而非CDB$ROOT - 若连在 CDB$ROOT,用
ALTER SESSION SET CONTAINER = pdb1;切换(需有SET CONTAINER权限) - 切换后,
CREATE USER app_user IDENTIFIED BY pwd;可直接执行,无需c##前缀,也不需要CONTAINER子句
关键点:PDB 内的用户是本地用户(local user),不受 ORA-65096 约束,且不会泄露到其他 PDB。
兼容旧脚本的最小改动方案
已有大量不含 c## 的建用户脚本要迁移到 12c+ CDB 环境?别全局替换用户名,优先做容器路由:
- 在脚本开头加判断逻辑(如通过
SELECT SYS_CONTEXT('USERENV', 'CON_NAME') FROM DUAL)区分当前容器 - 若为
CDB$ROOT,跳过用户创建,或仅创建极简的c##管理账号;核心业务用户一律在 PDB 中创建 - 自动化部署时,用
sqlplus / as sysdba @create_user.sql改为sqlplus /@pdb1 as sysdba @create_user.sql,直连目标 PDB
硬加 c## 前缀看似省事,但会让应用配置、审计日志、权限管理全部带上冗余前缀,后期维护成本远高于一次容器切换。
最易被忽略的一点:DEFAULT TABLESPACE 和 TEMPORARY TABLESPACE 必须在目标 PDB 中已存在,否则即使容器切对了,也会报 ORA-00959 —— 这个错常被误认为还是 ORA-65096 的衍生问题。

















