定义者权限(AUTHID DEFINER)以创建者身份执行,对象访问依赖创建者权限和Schema;调用者权限(AUTHID CURRENT_USER)以调用者身份执行,需调用者具备对应对象权限且操作其自身Schema数据。

AUTHID DEFINER 和 AUTHID CURRENT_USER 的核心区别不是“能不能执行”,而是“以谁的权限、在哪个 Schema 下执行”。
直接说结论:定义者权限(默认)靠创建者兜底,调用者权限靠调用者自己扛责。选错会导致权限报错、对象找不到、SQL 不共享,甚至安全越权。
定义者权限下 EXECUTE 权限就够了,但对象访问必须由创建者持有
只要被授予 EXECUTE 权限,任何用户都能调用定义者权限的存储过程,内部 SQL 用的是创建者的权限和 Schema。
- 创建者必须拥有过程里所有对象(表、视图、包等)的**直接授权**——通过角色授的权限无效
- 过程内写
SELECT * FROM employees,永远查的是创建者 Schema 下的employees,哪怕调用者自己也有同名表 - 调用者不需要对这些对象有任何权限,哪怕
SELECT或INSERT都没授过,也能成功 - 典型场景:统一数据出口,如 HR 提供一个封装好的
get_salary_report,让其他部门调用,但不开放底层表
调用者权限下 EXECUTE + 对象权限缺一不可
启用 AUTHID CURRENT_USER 后,过程变成“代入执行”——它会切换到调用者的 Schema,并检查调用者本人是否具备操作权限。
- 调用者必须有过程本身的
EXECUTE权限,还必须有过程里涉及对象的对应权限(如SELECT ON schema.table) - 过程内写
SELECT * FROM employees,实际查的是**调用者当前 Schema 下的employees**;如果调用者没这个表,或没授权,直接报ORA-00942 - 角色权限(如通过
CONNECT或自定义角色授予的权限)在这里是有效的,不像定义者权限下被忽略 - 典型场景:多租户 SaaS,每个客户一个 Schema,用同一套逻辑处理各自数据
DBMS_ 包、DDL、动态 SQL 的权限归属容易搞混
不管哪种权限模式,只要过程里用了 Oracle 内置包(如 DBMS_LOCK、DBMS_DDL)或执行了 DDL(CREATE TABLE),权限归属就取决于模式本身:
- 定义者权限过程:需要把
EXECUTE ON dbms_lock授给**过程创建者**(比如GRANT EXECUTE ON DBMS_LOCK TO hr) - 调用者权限过程:需要把
EXECUTE ON dbms_lock授给**每个可能调用它的用户**(比如GRANT EXECUTE ON DBMS_LOCK TO u1, u2) - 动态 SQL(
EXECUTE IMMEDIATE)在定义者权限下仍走创建者权限;但在调用者权限下,会按调用者身份解析对象名和权限,这点常被误认为“绕过限制”,其实只是更严格了
性能与共享池行为差异常被忽略
两种模式编译出来的 PL/SQL 代码在共享池里的行为不同,影响高并发下的硬解析和内存占用:
- 定义者权限:SQL 文本固定,不同用户调用同一过程,生成的游标可被共享(相同
SQL_ID) - 调用者权限:即使 SQL 文本一样,Oracle 会为不同调用者生成不同游标(不同
CHILD_NUMBER),因为绑定上下文(Schema、权限集)不同 -
V$SQL中查PARSING_SCHEMA_NAME能看出区别:定义者权限始终是创建者,调用者权限则是实际调用者
真正麻烦的从来不是语法怎么写,而是想清楚——你写的这个过程,到底是“代表谁干活”,以及“干的是谁的数据”。


















