zoukankan      html  css  js  c++  java
  • 不要乱动dual表

          今天在itpub上看到一个帖子,在删除表的时候出现问题:

    SQL> drop table t4;
    drop table t4
    *
    ERROR at line 1:
    ORA-00604: error occurred at recursive SQL level 1
    ORA-01422: exact fetch returns more than requested number of rows

          通常来说 drop table 失败的原因都是权限不足,但这次却报递归SQL出错,咋看让人摸不着头脑,随着版主的分析终于揭开了这个谜底——动了 dual 表。

          以下是我的实验过程重演这个问题。

          首先以一个测试用户(我这里是scott)创建一个普通表:

    scott@ora10g(oracle01) SQL> create table tab01(f01 int); 
    
    Table created.

          以 sys 用户向 dual 插入一条数据,并提交:

    sys@ora10g(oracle01) SQL> insert into dual values('Y');
    
    1 row created.
    
    sys@ora10g(oracle01) SQL> commit; 
    
    Commit complete.

          由于一些内部的实现,以下是 dual 比较怪异的情况:

    sys@ora10g(oracle01) SQL> select * from dual ; 
    
    D
    -
    X
    
    sys@ora10g(oracle01) SQL> select count(*) from dual  ;      
    
      COUNT(*)
    ----------
             1
    
    sys@ora10g(oracle01) SQL> begin 
      2  for x in (select * from dual) loop
      3    dbms_output.put_line(x.dummy);
      4  end loop;
      5  end;
      6  /
    X
    Y

          可以看到只有匿名过程返回的结果才是两条数据。

          此时以scott用户删除之前创建的测试表 tab01,即可触发帖子里面的问题:

    scott@ora10g(oracle01) SQL> drop table tab01 ; 
    drop table tab01
    *
    ERROR at line 1:
    ORA-00604: error occurred at recursive SQL level 1
    ORA-01422: exact fetch returns more than requested number of rows

          做一个级别为12的10046跟踪,尝试找出问题:

    scott@ora10g(oracle01) SQL> alter session set tracefile_identifier='drop_table_error'; 
    
    Session altered.
    
    scott@ora10g(oracle01) SQL> alter session set events'10046 trace name context forever,level 12';
    
    Session altered.
    
    scott@ora10g(oracle01) SQL> drop table tab01 ; 
    drop table tab01
    *
    ERROR at line 1:
    ORA-00604: error occurred at recursive SQL level 1
    ORA-01422: exact fetch returns more than requested number of rows
    
    scott@ora10g(oracle01) SQL> alter session set events '10046 trace name context off';

          经过 tkprof 处理后,可以找到为一个引用了 dual 的地方:

    select dummy 
    from
     dual where  ora_dict_obj_type = 'TABLE'
    ......
    ......
    Rows     Row Source Operation
    -------  ---------------------------------------------------
          2  FILTER  (cr=212 pr=2 pw=0 time=32261 us)
          2   TABLE ACCESS FULL DUAL (cr=3 pr=0 pw=0 time=0 us)

           删除了 dual 表中“多余”行后却是:

    select dummy 
    from
     dual where  ora_dict_obj_type = 'TABLE'
    ......
    ......
    Rows     Row Source Operation
    -------  ---------------------------------------------------
          1  FILTER  (cr=107 pr=0 pw=0 time=17082 us)
          1   TABLE ACCESS FULL DUAL (cr=3 pr=0 pw=0 time=0 us)

          当然 drop table 也没有再出错了。

  • 相关阅读:
    Sqlite && EF Code FIRST 终极解决方案 2019.5.17
    网卡 API 相关
    (依赖注入框架:Ninject ) 一 手写依赖注入
    Nlog 日志框架简单教程
    调试时候输出信息到输出窗口
    利用VS 性能探查器 解决代码性能不高问题
    Image 释放
    记一次数据丢失(电脑硬盘closed to down)的经历
    [极短]数字求和
    在博客园中使用pixijs
  • 原文地址:https://www.cnblogs.com/killkill/p/1841785.html
Copyright © 2011-2022 走看看