0
点赞
收藏
分享

微信扫一扫

奇怪的ORA-00942:表或视图不存在


一、 背景

     用户在数据库执行语句时遇到一个奇怪的报错,这个sql执行一共会返回500多万行数据,但每返回到400多万行时就报错ORA-00942:表或视图不存在(sql中所用表和包已授权)

此处省略报错sql
ERROR:
ORA-00942: table or view does not exist
ORA-06512: at "APPS.TEST_API", line 39
ORA-06512: at "APPS.TEST_API", line 679
ORA-06512: at line 1

4493670 rows selected.

可以看到报错的包是APPS.TEST_API

有几种方法可定位到报错的表:

  • 10046 trace:alter session set events '10046 trace name context forever,level 3';
  • 942事件trace:ALTER session SET EVENTS '942 trace name context forever, level 3'; 
  • 根据报错行数去存储过程里找对应的表

二、 解决方法

找到报错表后创建public同义词并给用户授权

create public synonym xxx for user1.xxx;
grant select on user1.xxx to user2;

这个问题定位和处理方法都不难,但想找一下根因。

有两个奇怪的问题:

  • 为什么用户已经有APPS.TEST_API包的执行权限还需要对其中的表额外授权?
  • 为什么能返回400多万行数据,而不是在语句编译时就报错?

三、 报错原因分析

1. 定义者权限 vs 调用者权限

①  AUTHID DEFINER(定义者权限,DR):指编译存储对象的所有者,也是默认权限模式。因此通常我们只需要授予用户包的执行权限,而不需要授予包中表的执行权限。

奇怪的ORA-00942:表或视图不存在_SQL

②  AUTHID CURRENT_USER(调用者权限,IR):指拥有当前会话权限的模式,这可能和当前登录用户相同或不同(alter session set current_schema 可以改变调用者Schema)。它以执行的用户权限来处理涉及的对象权限,这是典型的,数据库中只创建一个存储过程,所有用户都可以使用,但每个用户使用的时候只是用自己的权限执行。

奇怪的ORA-00942:表或视图不存在_定义者权限_02

根据报错的现象,其实符合IR的特点。查看报错包的定义:

create or replace package apps.test_api authid current user as ...

注意到authid current user as,可以看到确实用的就是IR,所以使用apps用户执行不会有这样的报错,而使用其他用户很可能就会报错表不存在。另外由于这个包是系统自带的,最好不要修改代码。

2.     动态sql vs 静态sql 权限检查过程

另外一个问题是,为什么能返回400多万行数据,而不是在语句编译时就报错

在官方文档中找到了这样一段介绍:

For dynamic SQL statements issued by a PL/SQL unit, name resolution and privilege checking are done once, at run time.

For static SQL statements, name resolution and privilege checking are done twice: first, when the PL/SQL unit is compiled, and then again at run time.

  • At compile time, the AUTHID property has no effect—both DR and IR units are treated like DR units.
  • At run time, however, the AUTHID property determines whether a unit is IR or DR, and the unit is treated accordingly.

对于plsql中的动态sql,Oracle只在运行阶段进行一次权限检查。

对于静态sql,则会检查两次。

  •        第一次在编译阶段,无论是DR还是IR,都当做DR处理,所以在编译阶段该sql没有报错
  •        第二次在运行阶段,此时会区分DR和IR,所以当运行到无权限表时就会报错。

四、 测试环境复现

apps用户创建测试对象

create or replace package testpkg AUTHID CURRENT_USER AS
procedure testpri;
procedure testpri_2;
end testpkg;
/

create or replace package body testpkg
as
procedure testpri
is
V_A number;
begin
select A into V_A from apps.test where rownum<2;
dbms_output.put_line(V_A);
end;
procedure testpri_2
is
V_B number;
begin
testpri;
select B into V_B from test2 where rownum<2;
dbms_output.put_line(V_B);
end;
end testpkg;
/

apps用户测试执行:正常输出

SQL> set serveroutput on
SQL> exec apps.testpkg.testpri_2;
1
2

PL/SQL procedure successfully completed.

apps用户授包执行权限给 TESTPRI 用户

grant execute on apps.testpkg to TESTPRI;
grant select on apps.test to TESTPRI;

conn TESTPRI/TESTPRI
SQL> set serveroutput on
SQL> exec apps.testpkg.testpri_2;
1

BEGIN apps.testpkg.testpri_2; END;
*
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at "APPS.TESTPKG", line 16
ORA-06512: at line 1

可以看到第一个存储过程执行正常而第二个存储过程执行就报错了

参考:

Authid current_user, authid definer | DBAORA

http://www.voidcn.com/article/p-sxctwtao-gc.html

PL/SQL Subprograms


举报

相关推荐

0 条评论