系统权限决定能否执行某类操作(如CREATE SESSION连接数据库),对象权限决定能否访问特定对象(如SELECT ON scott.emp);前者作用于全局,后者必须显式指定对象全名,且不可混用授权/回收语法。

系统权限决定“能不能做某类事”,对象权限决定“能不能动某个东西”
系统权限管的是动作边界,比如 CREATE SESSION 决定你能否连上数据库,CREATE TABLE 决定你能否建表——但不管建在谁的 schema 下;对象权限管的是数据边界,比如 SELECT ON scott.emp 只允许你查 scott 用户下的 emp 表,哪怕你有 CREATE TABLE,也默认看不到、改不了别人表里的数据。
常见混淆点:用户刚创建时只有 CREATE SESSION(如果被授予),但连 SELECT * FROM dual 都会报 ORA-00942,因为 dual 属于 SYS schema,而你没被授予访问它的对象权限(虽然 DBA 通常已预授权)。这说明:系统权限 ≠ 自动获得对所有对象的访问权。
授予权限的语法和主体完全不同
系统权限由具备 GRANT ANY PRIVILEGE 或 DBA 角色的用户授予,目标是用户或角色,不涉及具体对象:
GRANT CREATE TABLE, UNLIMITED TABLESPACE TO lisi;
对象权限必须由该对象的拥有者(或具备 GRANT ANY OBJECT PRIVILEGE 的用户)授予,且必须明确写出对象全名:
GRANT SELECT, INSERT ON wangwu.wangtab TO lisi;
-
wangwu.wangtab是完整对象引用,省略 schema 名(如只写wangtab)会默认找当前用户的同名表,不是跨 schema 授权 - 对象权限不能跨 schema 授予未存在的对象——
wangwu.wangtab必须已存在,否则报ORA-00942 - 用
WITH GRANT OPTION授予对象权限后,被授权者可转授,但系统权限要用WITH ADMIN OPTION,二者不可混用
回收权限时行为差异极大
系统权限回收不级联:A 授予 B CREATE TABLE(带 WITH ADMIN OPTION),B 又授给 C;若 A 收回 B 的权限,C 的权限依然有效。对象权限回收则严格按授权链走:A 授予 B SELECT ON t(带 WITH GRANT OPTION),B 授予 C,A 直接收回 B 的权限后,C 的权限立即失效。
另一个关键区别是回收范围:
- 系统权限可用
REVOKE CREATE TABLE FROM lisi直接回收,无需知道当初谁授的 - 对象权限必须由原拥有者或 DBA 执行回收,且要写全对象名:
REVOKE SELECT ON wangwu.wangtab FROM lisi - 误用
REVOKE SELECT ON wangtab FROM lisi(漏 schema)会报ORA-01927:无法撤销未授予的权限
查权限时必须选对数据字典视图
查自己有哪些系统权限,用 USER_SYS_PRIVS;查自己被授予了哪些对象权限,用 USER_TAB_PRIVS。但这两张视图只显示“当前用户直接受到的授权”,不反映间接继承或角色带来的权限。
真正容易踩坑的是:DBA 常用 DBA_SYS_PRIVS 和 DBA_TAB_PRIVS 查全局权限,但普通用户没权限访问这些视图。如果你在非 DBA 账户下执行:
SELECT * FROM dba_tab_privs WHERE grantee = 'LISI';
会直接报 ORA-00942——不是权限没设好,而是你根本没查这张表的权限。这时候应该先确认自己是否被授予了 SELECT_CATALOG_ROLE,或者老实用 USER_* 视图。
对象权限的“隐式依赖”最麻烦:比如你有 SELECT ON v_emp(视图),但视图底层查的是 scott.emp,而你没被授予 SELECT ON scott.emp,查询仍会失败。这种依赖关系不会出现在 USER_TAB_PRIVS 里,得靠人工梳理或用 ALL_DEPENDENCIES 辅助分析。











