【问题标题】:"Table or view does not exist" on create table创建表时“表或视图不存在”
【发布时间】:2013-09-30 08:48:19
【问题描述】:

我最近从我的代码中得到了一个非常奇怪的异常:

XXX.WrappedSqlException: ORA-00604: error occurred at recursive SQL level 1
ORA-00942: table or view does not exist

while executing create table ST_UTEST2_DATE (value varchar(100) not null unique,replacement varchar(100) not null)
            at XXX
Caused by: java.sql.SQLException: ORA-00604: error occurred at recursive SQL level 1
ORA-00942: table or view does not exist

            at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:445)
            at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
            at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:879)
            at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:450)
            at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192)
            at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531)
            at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:207)
            at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1037)
            at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1329)
            at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3584)
            at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:3685)
            at oracle.jdbc.driver.OraclePreparedStatementWrapper.execute(OraclePreparedStatementWrapper.java:1088)
            ... 8 more

该表确实不存在(在此次发布之前和之后)。当我想执行“创建表”时,通常就是这种情况。我不知道如何在创建表时获得“表或视图不存在”。

这个异常只被抛出一次。具有完全相同环境(数据库状态)的相同代码多次执行。有多个线程执行此代码(检查此表是否存在,如果不存在,则创建它),每个线程都有自己的连接。但是检查和创建发生的片段是同步的 - 表的执行肯定不会从多个线程同时发生,并且检查和创建是原子的。

欢迎任何可能产生此类异常的想法(包括疯狂猜测)。

数据库是Oracle 10g。

【问题讨论】:

    标签: java sql oracle


    【解决方案1】:

    如果数据字典损坏,这种情况很常见。阅读here 更多信息(不完全在创建表上,但这可能是同一个问题。尝试那里提供的解决方案)。您可能必须执行 catqueue.sql 脚本。在数据字典上运行任何脚本之前,您应该备份您的数据库。参考同样的讨论here

    【讨论】:

    • 在使用 Oracle 的 10 多年中,我从未遇到过损坏的数据字典。当然是 YMMV,但我不会说“这很常见”。
    • 是的,不会太频繁,但可能存在部分上传或上传失败
    【解决方案2】:

    我的猜测是架构级触发器尝试执行某种审计操作但失败了。

    一种可能的情况:

    • user1 拥有一个定义为 AUTHID CURRENT_USER(授予 user2)的日志记录包,该包插入到 user1 架构内的表中,无需显式指定表架构
    • user2 创建一个架构级触发器,用于记录 user2 架构内的所有 DDL 语句
    • user2 尝试创建表;这失败了,因为触发器触发了日志记录过程,该过程在 user2 架构中查找日志表并失败(因为该表不存在)

    用于重现此内容的 SQL 语句(假设用户 test1 已存在并具有 DBA 权限):

    -- create the log table
    CREATE TABLE ddl_log as 
    SELECT ora_sysevent,
                 ora_dict_obj_owner,
                 ora_dict_obj_name,
                 USER as ddl_user,
                 SYSDATE as ddl_date
            FROM DUAL
    WHERE 1=0;        
    
    -- create the logging package
    CREATE OR REPLACE PACKAGE pck_log_ddl AUTHID CURRENT_USER is
    
      PROCEDURE log_ddl;
    
    END pck_log_ddl;
    /
    create or replace package body pck_log_ddl is
    
      procedure log_ddl is
      begin
        INSERT INTO ddl_log
          SELECT ora_sysevent,
                 ora_dict_obj_owner,
                 ora_dict_obj_name,
                 USER,
                 SYSDATE
            FROM DUAL;
      end;
    
    end pck_log_ddl;
    
    -- create the second user
    create user test2 identified by test2;
    
    grant connect, resource, create table, create trigger to test2;
    grant execute on pck_log_ddl to test2;
    
    connect test2@mydb
    -- create the schema-level trigger
    CREATE OR REPLACE TRIGGER bcs_trigger
    BEFORE CREATE
    ON SCHEMA
    BEGIN
      test1.pkg_log_ddl.log_ddl;
    END bcs_trigger;
    
     -- try creating a table => ORA-00604 / ORA-00942
    create table ST_UTEST2_DATE (
       value varchar(100) not null unique,
       replacement varchar(100) not null
    );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多