ORA-65096错误源于CDB$ROOT中创建用户时必须使用C##前缀且显式指定CONTAINER=ALL,否则解析阶段即被硬编码校验拦截;正确做法是切换至目标PDB后创建无前缀用户。

ORA-65096不是拼写错误,是CDB$ROOT的硬编码拦截
你在CDB$ROOT里执行CREATE USER app_user IDENTIFIED BY pwd;,Oracle根本不会去查字典或参数,而是在SQL解析阶段就调用底层函数ksuCheckCommonUserName做正则匹配:必须满足^C##(大小写不敏感,但两个井号必须连续)。app_user、c#user、cc##user、甚至"c##user"全被拒——引号救不了,common_user_prefix参数改为空也救不了,因为校验逻辑已硬编码进内核。
CONTAINER=ALL不是可选开关,而是作用域声明
即使用户名带C##,漏写CONTAINER=ALL也会创建失败或创建出错的用户:
-
CREATE USER c##admin IDENTIFIED BY p123;→ 默认CONTAINER=CURRENT,只在CDB$ROOT建本地用户,不跨PDB -
CREATE USER c##admin IDENTIFIED BY p123 CONTAINER=ALL;→ 才算真正公共用户,但还需后续在各PDB中单独授权 -
GRANT CONNECT TO c##admin;不加CONTAINER=ALL→ 权限只生效于当前容器(通常是CDB$ROOT),PDB里仍无法登录
真想用无前缀用户名?别绕过,切PDB
绝大多数应用根本不需要跨PDB的公共用户。正确路径是主动切换容器上下文:
- 先确认目标PDB名称:
SELECT name FROM v$pdbs; - 切到PDB:
ALTER SESSION SET CONTAINER = hrpdb; - 此时
CREATE USER hr IDENTIFIED BY hr;完全合法,无需C##,也不触发ORA-65096 - 注意连接串必须指向该PDB的服务名(如
hrpdb),不能只用CDB的service_name
系统用户SYS/SYSTEM是例外,但别学它们
SYS和SYSTEM确实不用C##前缀,但这是Oracle内建白名单,不是规则漏洞。试图用_oracle_script等隐藏参数绕过校验,只适合临时测试环境,会破坏多租户元数据一致性——生产库一旦启用,后续升级或补丁可能直接拒绝启动。


















