Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
强制Oracle删除全局临时表_Oracle_Plsql_Ddl_Temp Tables - Fatal编程技术网

强制Oracle删除全局临时表

强制Oracle删除全局临时表,oracle,plsql,ddl,temp-tables,Oracle,Plsql,Ddl,Temp Tables,在我们的项目中,我创建了一些全局临时表,如下所示: CREATE GLOBAL TEMPORARY TABLE v2dtemp ( id NUMBER, GOOD_TYPE_GROUP VARCHAR2(250 BYTE), GOOD_CODE VARCHAR2(50 BYTE), GOOD_TITLE VARCHAR2(250 BYTE) ) ON COMMIT PRESERVE ROWS; 但当我

在我们的项目中,我创建了一些全局临时表,如下所示:

CREATE GLOBAL TEMPORARY TABLE v2dtemp (
  id           NUMBER,
  GOOD_TYPE_GROUP       VARCHAR2(250 BYTE),
  GOOD_CODE             VARCHAR2(50 BYTE),
  GOOD_TITLE            VARCHAR2(250 BYTE)
)
ON COMMIT PRESERVE ROWS;
但当我想放下这张桌子时,问题就来了。 Oracle不会让我放弃这张表,它说:

ORA-14452: attempt to create, alter or drop an index on temporary table already in use
我必须在某些程序中使用此表,但它可能会根据其他报告进行更改。因此,我应该始终删除表,然后使用所需字段重新创建它

出于某些商业原因,我不得不使用它,所以我不可能使用表或其他东西。我可以只使用临时表。 我尝试了commit delete rows,但当我调用我的过程来使用此表中的数据时,表中没有更多的行,它们已被删除

任何帮助都将不胜感激, 提前谢谢

///编辑

public void saveJSONBatchOpenJobs(final JSONArray array, MtdReport report) {
    dropAndCreateTable();
    String sql = "INSERT INTO v2d_temp " +
            "(ID, KARPARDAZ, GOOD_TYPE_GROUP, GOOD_CODE, GOOD_TITLE, COUNT, "
            + "FACTOR_COUNT, GHABZ_COUNT, DEAL_NO, DEAL_DATE, REQUEST_NO, REQUEST_DATE, "
            + "REQUEST_CLIENT, STATUS, TYPE, MTDREPORT_ID, GEN_SECURITY_DATA_ID) " +
            "VALUES (MTD_KARPARDAZ_OPEN_JOBS_SEQ.nextval,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

    getJdbcTemplate().batchUpdate(sql, new BatchPreparedStatementSetter() {

        @Override
        public void setValues(PreparedStatement ps, int i) throws SQLException {
            JSONArray values = array.getJSONArray(i);
            if(!values.get(0).equals("null"))
                ps.setString(1, values.get(0).toString());
            else
                ps.setNull(1, Types.VARCHAR);
            if(!values.get(1).equals("null"))
                ps.setString(2, values.get(1).toString());
            else
                ps.setNull(2, Types.VARCHAR);
            if(!values.get(2).equals("null"))
                ps.setString(3, values.get(2).toString());
            else
                ps.setNull(3, Types.VARCHAR);
            if(!values.get(3).equals("null"))
                ps.setString(4, values.get(3).toString());
            else
                ps.setNull(4, Types.VARCHAR);
            if(!values.get(4).equals("null"))
                ps.setBigDecimal(5, new BigDecimal(values.get(4).toString()));
            else
                ps.setNull(5, Types.NUMERIC);
            if(!values.get(5).equals("null"))
                ps.setBigDecimal(6, new BigDecimal(values.get(5).toString()));
            else
                ps.setNull(6, Types.NUMERIC);
            if(!values.get(6).equals("null"))
                ps.setBigDecimal(7, new BigDecimal(values.get(6).toString()));
            else
                ps.setNull(7, Types.NUMERIC);
            if(!values.get(7).equals("null"))
                ps.setString(8, values.get(7).toString());
            else
                ps.setNull(8, Types.VARCHAR);
            if(!values.get(8).equals("null"))
                ps.setDate(9, new Date(new Timestamp(values.getLong(8)).getDateTime()));
            else
                ps.setNull(9, Types.DATE);
            if(!values.get(9).equals("null"))
                ps.setString(10, values.get(9).toString());
            else
                ps.setNull(10, Types.VARCHAR);
            if(!values.get(10).equals("null"))
                ps.setDate(11, new Date(new Timestamp(values.getLong(8)).getDateTime()));
            else
                ps.setNull(11, Types.DATE);
            if(!values.get(11).equals("null"))
                ps.setString(12, values.get(11).toString());
            else
                ps.setNull(12, Types.VARCHAR);
            if(!values.get(12).equals("null"))
                ps.setString(13, values.get(12).toString());
            else
                ps.setNull(13, Types.VARCHAR);
            if(!values.get(13).equals("null"))
                ps.setString(14, values.get(13).toString());
            else
                ps.setNull(14, Types.VARCHAR);
            if(!values.get(14).equals("null"))
                ps.setLong(15, new Long(values.get(14).toString()));
            else
                ps.setNull(15, Types.NUMERIC);
            if(!values.get(15).equals("null"))
                ps.setLong(16, new Long(values.get(15).toString()));
            else
                ps.setNull(16, Types.NUMERIC);
        }

        @Override
        public int getBatchSize() {
            return array.size();
        }
    });

    String bulkInsert = "declare "
            + "type array is table of d2v_temp%rowtype;"
            + "t1 array;"
            + "begin "
            + "select * bulk collect into t1 from d2v_temp;"
            + "forall i in t1.first..t1.last "
            + "insert into vertical_design values t1(i);"
            + "end;";
    executeSQL(bulkInsert);
}

private void dropAndCreateTable() {
    String dropSql = "declare c int;"
            + "begin "
            + "select count(*) into c from user_tables where table_name = upper('v2d_temp');"
            + "if c = 1 then "
            + "truncate table v2d_temp"
            + "drop table v2d_temp;"
            + " end if;"
            + "end;";
    executeSQL(dropSql);

    String createSql = "CREATE GLOBAL TEMPORARY TABLE v2d_temp (\n"
            + "DEAL_ID               NUMBER,\n"
            + "id           NUMBER,\n"
            + "karpardaz  VARCHAR2(350),\n"
            + "GOOD_TYPE_GROUP       VARCHAR2(250 BYTE),\n"
            + "GOOD_CODE             VARCHAR2(50 BYTE),\n"
            + "GOOD_TITLE            VARCHAR2(250 BYTE),\n"
            + "COUNT                 NUMBER,\n"
            + "FACTOR_COUNT          NUMBER,\n"
            + "GHABZ_COUNT           NUMBER,\n"
            + "DEAL_NO               VARCHAR2(50 BYTE),\n"
            + "DEAL_DATE             DATE,\n"
            + "REQUEST_NO            VARCHAR2(50 BYTE),\n"
            + "REQUEST_DATE          DATE,\n"
            + "REQUEST_CLIENT        VARCHAR2(250 BYTE),\n"
            + "STATUS                VARCHAR2(250 BYTE),\n"
            + "TYPE                  VARCHAR2(250 BYTE),\n"
            + "GEN_SECURITY_DATA_ID  NUMBER(10),\n"
            + "MTDREPORT_ID          NUMBER\n"
            + ")\n"
            + "ON COMMIT PRESERVE ROWS";
    executeSQL(createSql);
}

private void executeSQL(String sql) {
    Connection con = null;
    try {
        con = getConnection();
        Statement st = con.createStatement();
        st.execute(sql);
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        if(con != null) {
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

Oracle全局临时表不是临时对象。它们是适当的堆表。我们创建它们一次,任何会话都可以使用它们来存储仅对该会话可见的数据

临时方面是数据在一个事务或一个会话之后不会持久化。关键的实现细节是将数据写入临时表空间,而不是永久表空间。但是,数据仍然被写入磁盘或从磁盘读取,因此使用全局临时表会带来显著的开销

关键是我们不应该删除并重新创建临时表。如果您试图将SQLServer样式逻辑移植到Oracle中,则应该考虑使用PL/SQL集合来维护内存中的临时数据。p>
ORA-14452
的具体原因是,如果全局临时表在会话期间包含数据,则无法删除具有会话范围持久性的全局临时表。即使表当前为空

SQL> create global temporary table gtt23 (col1 number)
  2  on commit preserve rows
  3  /

Table created.

SQL> insert into gtt23 values (1);

1 row created.

SQL> commit;

Commit complete.

SQL> delete from gtt23;

1 row deleted.

SQL> commit;

Commit complete.

SQL> drop table gtt23;
drop table gtt23
           *
ERROR at line 1:
ORA-14452: attempt to create, alter or drop an index on temporary table already in use

SQL>
解决方案是结束会话并重新连接,或者(有点奇怪)截断表,然后删除它

SQL> truncate table gtt23;

Table truncated.

SQL> drop table gtt23;

Table dropped.

SQL> 
如果其他会话正在使用全局临时表-这是可能的(因此使用全局命名法),那么在所有会话断开连接之前,您将无法删除该表

因此,真正的解决方案是学会正确使用全局临时表:创建特定的全局临时表以匹配每个报表。或者,如我所说,改用PL/SQL集合。或者,甚至只是学习编写经过良好调优的SQL。通常,我们使用临时表作为一种解决方法,以避免编写不好的查询,而这些查询可以通过更好的访问路径保存


查看了完整的代码后,流程看起来更奇怪:

  • 删除并重新创建全局临时表
  • 填充临时表
  • 从临时表中选择到PL/SQL数组中
  • 使用PL/SQL数组中的大容量插入将数据插入到实际表中
  • 这里有太多的开销和浪费的活动。您所需要做的就是将插入到
    v2d\u temp
    中的数据直接填充到
    vertical\u design
    ,理想情况下插入到。。。从语句中选择*FROM。将JSON数组转换为查询需要一些预处理,但这在Java或PL/SQL中都很容易实现

    在我看来,全局临时表并不是适合您的场景的正确解决方案


    “我们的老板或其他人坚持按自己的方式做事,所以你无法改变”

    您遇到的是老板问题而不是编程问题。因此,就StackOverflow而言,它是离题的。但这里还是有一些建议

    要记住的关键一点是,我们不是在讨论一些次优架构的折衷方案:您的老板提出的方案显然在多用户环境中不起作用。因此,您的选择是:

  • 忽略
    ORA-14452
    错误,继续生产,然后在出现严重错误时使用“但你告诉我要”防御。这是最弱的一出戏
  • 秘密地丢弃全局表并实现一些在多用户场景中可以工作的东西。这是高风险的,因为如果你把实现搞砸了,你就没有防御措施
  • 和你的老板谈谈。告诉他们您遇到了
    ORA-14452
    错误,说您已经做了一些调查,以这种方式使用全局临时表似乎是一个基本问题,但显然您忽略了一些东西。然后,问他们以前实现过这个问题,他们是如何解决这个问题的。这可能有多种方式,也许他们有解决办法,也许他们会意识到这是使用全局临时表的错误方式,也许他们会告诉你滚开。无论哪种方式,这都是最好的方法:您已将关注点提升到适当的级别

  • 祝你好运。

    终止会话是解决ORA-14452错误的唯一方法。使用数据字典查找使用临时表的其他会话并杀死它们 使用类似于
    alter system kill session'sid,seriall#,instance_id'的语句

    这是Oracle支持文档中提到的“官方”解决方案 如何在删除临时表(文档ID 800506.1)期间诊断ORA-14452。我过去曾成功地使用过这种方法,原因稍有不同。 终止会话需要提升权限,而且可能很棘手;它可能需要杀戮、等待,然后重试几次

    出于许多原因,这种解决方案几乎肯定是个坏主意。在实现此功能之前,您应该尝试利用此信息来证明这是正确的 这是错误的做法。例如,“Oracle文档说明此方法需要
    alter system
    特权,这是危险的,会引起一些问题
    安全问题…。

    另一个值得考虑的方法是重新考虑是否需要临时表

    在那些从其他RDBMS过渡到Oracle而过度使用它们的人中,这是一种非常常见的编程实践,因为他们不理解您可以将这些特性作为通用特性来使用
    SELECT * FROM V$SESSION
    
    ALTER SYSTEM DISCONNECT SESSION ‘sid,serial#’ POST_TRANSACTION
    
    ALTER SYSTEM DISCONNECT SESSION ‘sid,serial#’ IMMEDIATE