触发器默认以AUTHID DEFINER模式运行,仅依赖创建者直接权限,不继承角色权限;若需使用角色权限,须显式声明AUTHID CURRENT_USER,并确保调用者用户已启用对应角色且拥有对象的直接授权。
触发器默认运行在 DEFINER’S RIGHTS 模式下
oracle 触发器(以及存储过程、函数)默认以定义者权限(authid definer)执行,也就是说,它只认“创建该触发器的用户”所**直接拥有**的权限,完全忽略当前会话启用的角色及其带来的权限。哪怕你 set role all 后再执行 dml,触发器内部仍看不到角色授予的 select、insert 等对象权限。
角色权限在 PL/SQL 命名块中被显式禁用
这是 Oracle 的硬性安全限制,不是 Bug。从 8i 开始就如此设计:所有命名 PL/SQL 单元(包括触发器)在编译和运行时,都不会解析或继承通过角色获得的权限。即使角色已启用、SESSION_ROLES 显示为 ENABLED,触发器里查 other_schema.t 仍会报 ORA-01031。
- 触发器编译阶段不校验动态 SQL 权限,只检查静态引用对象——但即便静态引用,也要求定义者直有权限
- 动态 SQL(如
EXECUTE IMMEDIATE)执行时,同样受限于定义者权限模型,角色权限无效 -
SELECT_CATALOG_ROLE这类预定义角色,在触发器里对DBA_*视图的访问也失效
怎么让触发器用上角色权限?
唯一合规路径是改用调用者权限模式,但需满足严格前提:
- 触发器必须显式声明
AUTHID CURRENT_USER - 触发器所属用户本身必须有
CREATE TRIGGER权限(不能仅靠角色) - 实际执行触发的用户(即 DML 发起者),必须已启用对应角色,且角色中包含所需对象权限
- 注意:若触发器操作跨 schema 表,该表权限必须由属主**直接授予调用者用户**,不能仅靠角色间接授予
示例:CREATE OR REPLACE TRIGGER t1_trig AUTHID CURRENT_USER BEFORE INSERT ON t1 ... —— 此时触发器内语句使用的权限,来自执行 INSERT INTO t1 的那个用户当前会话的实际权限(含已启用角色)。
最容易被忽略的隐性依赖
很多人以为只要触发器能成功创建,就能跑通。但真实场景中,常因以下两点当场失败:
- 触发器里引用了同义词(synonym),而该同义词指向其他 schema 对象——同义词解析依赖定义者权限,若定义者没权限,哪怕调用者有也不行
- 触发器调用了另一个存储过程,而该过程是
AUTHID DEFINER—— 权限链在调用处中断,不会自动继承调用者上下文 - 使用
DBMS_SCHEDULER或DBMS_JOB异步触发时,作业运行在独立会话中,默认不启用任何角色,SESSION_ROLES为空


















