包编译成功不等于普通用户能执行,因oracle不继承角色权限,需对包及所有依赖对象(表、视图、函数等)显式授予execute/select等权限,且跨schema授权须带with grant option。

包编译成功 ≠ 普通用户能执行
编译通过只说明语法和对象依赖在当前会话(通常是包所有者)下成立,不校验调用者的权限。普通用户执行时抛 ORA-01031: insufficient privileges,根本原因是:包体中调用的底层对象(表、视图、函数、其他包过程等)未对调用者显式授权,且 Oracle 不继承角色权限到 PL/SQL 运行时上下文。
EXECUTE 权限必须显式授予,不能靠角色
即使你给用户 webuser 授予了 RESOURCE、CONNECT 或自定义角色,只要该角色包含 EXECUTE ON pkg_name,运行时仍会失败。Oracle 在存储过程/包执行期间会忽略角色权限。
- 正确做法是:由包所有者(或 DBA)执行
GRANT EXECUTE ON schema.pkg_name TO webuser; - 如果包里查询了
hr.employees,还需额外执行GRANT SELECT ON hr.employees TO webuser;(或通过WITH GRANT OPTION链式授权) - 检查是否漏掉包内调用的私有子程序——它们不可被外部直接授权,必须确保整个包的
EXECUTE权限已授出
包里访问跨 schema 对象时,权限链容易断在中间
常见断点不是“没给包权限”,而是包依赖的某个基表或视图,其所有者没把权限带 WITH GRANT OPTION 转授给包所有者。例如:
-
pkg_report在用户app下,内部SELECT * FROM hr.dept -
hr用户只执行了GRANT SELECT ON dept TO app;→ ❌ 不够 - 必须是
GRANT SELECT ON dept TO app WITH GRANT OPTION;→ ✅ 否则app无法让webuser通过包间接访问 - 否则调用时实际报错可能是
ORA-00942(表不存在)或ORA-01031,取决于 Oracle 版本和权限检查时机
排查时别只看包本身,要顺藤摸瓜查依赖
用以下语句定位包里到底用了哪些外部对象:
SELECT referenced_owner, referenced_name, referenced_type
FROM all_dependencies
WHERE name = 'PKG_NAME' AND owner = 'SCHEMA'
AND referenced_owner NOT IN ('SYS', 'SYSTEM');
然后逐个确认这些对象是否对目标用户授予了对应权限(SELECT、EXECUTE、INSERT 等)。最容易被忽略的是包里调用的另一个包的函数,或者动态 SQL 中拼接的表名——它们不会出现在编译期依赖检查里,但运行时缺权限一样报错。











