前阵子有个朋友从 MySQL 转到 Oracle,接手一个小型业务库。他觉得自己在 MySQL 里“建账号、给权限”已经熟得不能再熟,于是照着惯性写了一条 CREATE USER,结果登录直接报 ORA-01045,建表又报 ORA-01950,想查另一套 schema 的表还报 ORA-00942。他把三个报错一起截图发我,配了一句:Oracle 是不是每走一步都要单独开一次权限?
我说,你算是问到点子上了。跟 MySQL 那种“授权一次就基本全通”的模型不同,Oracle 里一个普通用户从出生到能真正干活,中间至少隔着“创建用户、授予会话权限、授予对象权限、处理表空间配额”四道工序。任何一道漏了,应用跑起来都会以各种看不懂的报错来提醒你。这篇文章就是把“Oracle 普通用户创建和授权”这件事从头到尾拆开讲清楚。无论你是刚转 Oracle 的开发,还是要给应用系统建号的运维,照着下面的思路走,能少踩很多坑。
1. 先把 Oracle 的“用户”模型理清楚:为什么这里没有一键授权
1.1 Oracle 的用户和 Schema 是一一对应的
MySQL 里有独立的 database,库下面有表,用户可以被授权访问某个库。Oracle 的逻辑不太一样:每个用户创建后,会自动带一个和用户名完全相同的 schema,这个 schema 是用户默认的对象容器。用户在自己 schema 里建的表、视图、存储过程,天然属于自己,不需要额外授权。
所以 Oracle 里“普通用户”这个概念,本质上不是指权限很小的用户,而是指“没有 DBA 这类管理角色的应用账号或业务账号”。这类用户通常只负责访问自己的对象,或者被授权去访问其他 schema 的对象。
这里有个很容易被忽略的点:Oracle 里的授权单位不是“库”,而是“用户/schema”和“具体对象”。你想让一个新用户读取 scott 用户的 emp 表,不能写“允许访问 scott”,而必须明确写“允许访问 scott.emp”。这种细粒度的设计,刚开始会觉得麻烦,但习惯后会发现权限边界非常清晰。
1.2 12c 之后的容器数据库环境,建用户之前先确认容器位置
如果你用的是 Oracle 12c 之后的版本,那么数据库默认有容器架构 CDB 和 PDB。CDB 是根容器,PDB 是真正的业务数据库。
在这个架构下建普通用户,最容易踩的坑是:用 sys 登录 CDB 后直接执行 CREATE USER,系统提示 ORA-65096: invalid common user or role name。原因很简单,你在 CDB 根容器里只能创建以 C## 开头的公共用户,普通业务用户不应该建在根容器里。
正确做法是先切到业务 PDB,再创建用户。比如:
sql复制ALTER SESSION SET CONTAINER = pdb01;
CREATE USER app_user IDENTIFIED BY "你的密码";
注意:如果你习惯用图形化工具连接,很多工具默认连到的就是某个 PDB,这时反而不用手工切容器。但用命令行操作时,这个步骤很高频,建议把它刻进肌肉记忆。
1.3 别把“普通用户”和“低权限用户”混为一谈
普通用户只是相对于管理员的概念,不代表权限必须少到可怜。一个典型的业务应用账号,可能需要建表、建索引、执行存储过程、访问若干个业务 schema,这些都是普通用户能做的事。
所以真正的问题不是“这个用户普通不普通”,而是“这个账号的业务边界在哪”。我见过不少项目给应用账号直接赋了 DBA 角色,省事是省事,但后果也严重:应用一旦被注入 SQL,攻击者能直接操作整个数据库;日常误操作时也完全没有边界保护。普通用户创建和授权,核心思路永远是围绕业务需求做最小授权,而不是按“好不好用”来做。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 建号实操:从一行 CREATE USER 到账号可登录
2.1 一条可以直接改着用的建号语句
先给一条我日常推荐的建号语句,它比网上很多示例多了 DEFAULT TABLESPACE、TEMPORARY TABLESPACE、PROFILE 和 QUOTA,这几个参数决定了账号以后会不会遇到奇奇怪怪的问题。
sql复制CREATE USER app_rw
IDENTIFIED BY "Init#2025"
DEFAULT TABLESPACE tbs_app_data
TEMPORARY TABLESPACE temp
PROFILE app_profile
QUOTA 500M ON tbs_app_data
QUOTA 0M ON system;
这条语句的意图是:
IDENTIFIED BY指定登录密码,注意 Oracle 12c 之后默认启用了密码大小写敏感,最好用带大小写和特殊字符的强密码,并用双引号包起来避免转义问题。DEFAULT TABLESPACE指定用户默认建表所在的表空间。如果不指定,会落到数据库默认表空间,通常就是 system,没人希望应用表建在 system 里。TEMPORARY TABLESPACE指定排序、
