ORA-01031 报错主因是过程创建者(schema_a)缺少对被引用对象的显式权限,而非调用者权限不足;因默认DEFINER'S RIGHTS模式下过程以schema_a身份运行,须逐个授予schema_a对schema_b.sales等对象的SELECT/EXECUTE权,角色无效,同义词不传递权限,AUTHID CURRENT_USER易致权限失控。

ORA-01031 报错时,99% 不是调用语句写错了,而是权限链断在了过程内部——你给了调用者权,没给过程创建者权。
为什么 EXEC schema_a.proc 报 ORA-01031?
Oracle 默认用DEFINER'S RIGHTS 执行存储过程,过程以 schema_a 身份运行,不是以调用者身份。所以:
如果 schema_a.proc 里写了 SELECT * FROM schema_b.sales 或调用了 schema_b.calc_total(),那么 schema_a 必须有对 schema_b.sales 的 SELECT 权、对 schema_b.calc_total 的 EXECUTE 权。
只给调用用户(比如 user_c)授 EXECUTE ON schema_a.proc 是不够的。
常见误判:DBA 查到 user_c 有 EXECUTE 权、schema_a 有 DBA 角色,仍失败——因为角色在定义者权限模式下不生效,必须显式授权。
怎么授全权限才不漏?
权限要分层、按实际引用路径逐个授予,不能靠角色或“一揽子授权”:- 先确认过程体里到底访问了哪些对象:查
dba_source或直接看代码,找出所有带 Schema 前缀的表、视图、函数、包过程,例如schema_b.sales、schema_b.pkg_name.func_x - 对每个被引用对象,执行显式授权:
GRANT SELECT ON schema_b.sales TO schema_a;、GRANT EXECUTE ON schema_b.calc_total TO schema_a;、GRANT EXECUTE ON schema_b.pkg_name TO schema_a; - 再授调用权:
GRANT EXECUTE ON schema_a.proc TO user_c; - 如果过程里还调用了包内过程,限定名必须写全:
schema_b.pkg_name.proc_in_pkg,且需单独授EXECUTE ON schema_b.pkg_name(不是只授包里某个过程)
同义词要不要建?
同义词只是别名,它不传递权限,也不解决跨 Schema 调用的本质问题:建了 CREATE SYNONYM proc FOR schema_a.proc 后,user_c 还是要被授 EXECUTE ON schema_a.proc,否则照样报 ORA-00904 或 ORA-01031。
更麻烦的是:多个 Schema 都建同名同义词(比如都叫 report),查询时实际解析到哪个,取决于当前会话的 SEARCH_PATH 和同义词类型(私有/公有),极易出错。
真正省事又可靠的做法:调用方直接写 schema_a.proc,部署脚本里不依赖同义词,避免漏建、覆盖、失效等维护陷阱。
能用 AUTHID CURRENT_USER 绕过吗?
可以,但代价明确:加 AUTHID CURRENT_USER 后,过程改用调用者身份执行,user_c 只要自己有 EXECUTE ON schema_a.proc 和 EXECUTE ON schema_b.calc_total 就能跑通。
但随之而来的是权限管理失控:每个调用者都得单独配下游所有权限,DBA 没法从过程定义反推依赖,审计困难;而且如果 user_c 依赖角色(如 SELECT_CATALOG_ROLE),还得确保该角色在会话中已启用(SET ROLE),否则仍失败。
生产环境强烈建议坚持 DEFINER'S RIGHTS + 显式授权,把权限边界收束在 Schema 级,而不是散落在每个调用用户身上。
跨 Schema 调用最易被忽略的点,不是“怎么写调用语句”,而是过程体里那几行看似普通的 schema_b.xxx ——它们才是权限链真正的断点位置。每次修改过程逻辑,只要新增了跨 Schema 引用,就必须同步补授权,缺一不可。


















