首页 » ORACLE » ora-942 or ora-1775 or PLS-00201 When using a database link in a stored procedure

ora-942 or ora-1775 or PLS-00201 When using a database link in a stored procedure

今天有网友在群里咨询一个问题,很有意思记录一下,希望别人遇到时可以得到提示。
Question:

有一个procedure中一段SQL用到了synynom,而synonym指向一个dblink所对应的表,其中是两个子查询做了full join,在procedure 编译时提示ORA-00942: table or view does not exist,而把那段plsql 查询语句块拿出来,做为单条SQL执行时完全正常且有返回结果,从user_errors可以得到错误定位指向synonym对象,问是不是full join和synonym配合出了问题?

Answer:
当然首先排除了procedrue授权的问题,其实后来也排除了与synonym和full join没有任何关系,问题是出在database link。

下面我来还原这个问题,测试是在11.2.0.3 for linux x86 64bit

1,第一步先演示ora-1775, 从168.231 db231 创建dblink到191.3 devdb

[oracle@db231 ~]$ /sbin/ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 00:22:19:5B:85:66  
          inet addr:192.168.168.231  Bcast:192.168.168.255  Mask:255.255.255.0
          inet6 addr: fe80::222:19ff:fe5b:8566/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8637 errors:0 dropped:0 overruns:0 frame:0
          TX packets:567 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:652529 (637.2 KiB)  TX bytes:75401 (73.6 KiB)
          Interrupt:36 Memory:d6000000-d6012800 

[oracle@db231 ~]$ tnsping d1913 

TNS Ping Utility for Linux: Version 11.2.0.3.0 - Production on 03-JUL-2014 15:39:04
Copyright (c) 1997, 2011, Oracle.  All rights reserved.

Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.191.3)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = devdb)))
OK (0 msec)

[oracle@db231 ~]$ sqlplus icme/icme@d1913;    
SQL*Plus: Release 11.2.0.3.0 Production on Thu Jul 3 15:40:48 2014
Copyright (c) 1982, 2011, Oracle.  All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

icme@DEVDB>

system@DEVDB>show parameter case
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
sec_case_sensitive_logon             boolean     FALSE

[oracle@db231 ~]$ sqlplus anbob/anbob

SQL*Plus: Release 11.2.0.3.0 Production on Thu Jul 3 15:41:23 2014
Copyright (c) 1982, 2011, Oracle.  All rights reserved.

anbob@ANBOB>create database link dl_1913_icme connect to "icme" identified by "icme" using 'd1913';
Database link created.

anbob@ANBOB>select count(*) from icme_org@dl_1913_icme;
            COUNT(*)
--------------------
              230957

anbob@ANBOB>create or replace procedure ptest 
 is
 v_n number;
 begin
 select count(*) into v_n from icme_org@dl_1913_icme;
 dbms_output.put_line(v_n);
 end;
 /

Warning: Procedure created with compilation errors.

anbob@ANBOB>show error
Errors for PROCEDURE PTEST:

LINE/COL ERROR
-------- -----------------------------------------------------------------
5/1      PL/SQL: SQL Statement ignored
5/1      PL/SQL: ORA-01775: looping chain of synonyms

10046 event
=====================
PARSE ERROR #139759914257600:len=50 dep=1 uid=84 oct=3 lid=84 tim=1404380353047265 err=942
SELECT * FROM "icme"."ICME_ORG"@"DL_1913_ICME.COM"

#甚至更离谱是有,虽然远端的确存在icme6 schema,不知O在解析时怎么遍历的到其它SCHEMA的。
=====================
PARSE ERROR #139759914257600:len=51 dep=1 uid=84 oct=3 lid=84 tim=1404380353053239 err=1031
SELECT * FROM "ICME6"."ICME_ORG"@"DL_1913_ICME.COM"

note:
我找了另外几个库10.2.0.5 ,10.2.0.4 连接到devdb结果同上,暂时未找到原因。

解决方法1

anbob@ANBOB>create database link dl_1913_icme2 connect to icme identified by "icme" using 'd1913'  ;
Database link created.

anbob@ANBOB>create or replace procedure ptest 
   is
   v_n number;
   begin
   select count(*) into v_n from icme_org@dl_1913_icme2;
   dbms_output.put_line(v_n);
   end;
   /
Procedure created.

anbob@ANBOB>exec ptest;
230957
PL/SQL procedure successfully completed.

anbob@ANBOB>select count(*) from icme_org@dl_1913_icme2;
            COUNT(*)
--------------------
              230957

Note:
注意创建DBLINK 时相比以前在用户上少了双引号
解决方法2

anbob@ANBOB>create or replace procedure ptest 
  is
  v_n number;
  begin
  select count(*) into v_n from icme.icme_org@dl_1913_icme;
  dbms_output.put_line(v_n);
  end;
  /
Procedure created.

anbob@ANBOB>exec ptest;
230957
PL/SQL procedure successfully completed.

Note: 还是原来的DB link,只是在对象前加了link 对象的用户名, 不知道这算不算一种解决方案,不过更建议用第一种。
2,第二步先演示ora-942, 从191.3 devdb 创建dblink到168.231 db231

[oracle@dev-db admin]$ tnsping d168231
TNS Ping Utility for Linux: Version 11.2.0.3.0 - Production on 03-JUL-2014 18:34:58
Copyright (c) 1997, 2011, Oracle.  All rights reserved.

Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.168.231)(PORT = 1521))) (CONNECT_DATA = (SERVICE_NAME = anbob.com)))
OK (10 msec)

anbob@ANBOB>show parameter case
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
sec_case_sensitive_logon             boolean     TRUE

system@DEVDB>create database link dl_231_anbob connect to "anbob" identified by "anbob" using 'd168231';
Database link created.

system@DEVDB>select count(*) from t@dl_231_anbob;
            COUNT(*)
--------------------
              851968

system@DEVDB>create or replace procedure ptest 
  2     is
  3     v_n number;
  4     begin
  5     select count(*) into v_n from t@dl_231_anbob;
  6     dbms_output.put_line(v_n);
  7     end;
  8     /

Warning: Procedure created with compilation errors.

system@DEVDB>show error
Errors for PROCEDURE PTEST:

LINE/COL ERROR
-------- -----------------------------------------------------------------
5/4      PL/SQL: SQL Statement ignored
5/34     PL/SQL: ORA-00942: table or view does not exist

system@DEVDB>create or replace procedure ptest 
  2     is
  3     v_n number;
  4     begin
  5     select count(*) into v_n from anbob.t@dl_231_anbob;
  6     dbms_output.put_line(v_n);
  7     end;
  8     /
Procedure created.

system@DEVDB>exec ptest;
851968
PL/SQL procedure successfully completed.

system@DEVDB>create database link dl_231_anbob2 connect to anbob identified by "anbob" using 'd168231';
Database link created.

system@DEVDB>create or replace procedure ptest 
  2     is
  3     v_n number;
  4     begin
  5     select count(*) into v_n from t@dl_231_anbob2;
  6     dbms_output.put_line(v_n);
  7     end;
  8     /
Procedure created.

system@DEVDB>exec ptest;
851968
PL/SQL procedure successfully completed.

Note:
最后发现MOS note 1353142.1 记录了ora-942 这个问题影响版本是10.2.0.4 and later,有意思是据记录曾经在版本8.1.7定位是Bug 2348742并在当时版本修复, 不知为何再次被唤醒(猜测是当时的开发出于马虎了事,挖坑给了后人)。另外还有一种情况没有测试,据网上收集资料发现因为11G 密码默认区分大小写,如果密码有时不带引号时也会有可能遇到密码错误。

Summary:
1,用户名和密码都带双引号,可能会:SQL 正常 ,PL/SQL(Procedure)不正常;
2,用户名密码都不带双引号,可能会:SQL密码错误,PL/SQL 正常
3,用记名不带双引号,密码带双引号,SQL 和PL/SQL 都正常

养成一个良好的语法习惯是多么的重要。今天看到Oracle还可以像MySQL一样的创建用户的语法:grant connect, resource to usr1 identified by usr1;

打赏

对不起,这篇文章暂时关闭评论。