加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

强制Oracle Drop全局临时表

发布时间:2020-12-12 15:14:30 所属栏目:百科 来源:网络整理
导读:在我们的项目中,我创建了一些全局临时表,如下所示: 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;

但问题出现的时候我想放弃这张桌子.
甲骨文不会让我放弃表,它说:

ORA-14452: attempt to create,alter or drop an index on temporary table already in use

我必须在某些过程中使用此表,但可能会根据其他报告进行更改.所以我应该总是丢弃表,然后我应该用我需要的字段重新创建它.

出于某些商业原因,我必须使用它,所以我不可能使用表格或其他东西.我只能使用临时表.
我尝试了提交删除行,但是当我调用我的过程来使用此表中的数据时,表中没有更多行,并且它们已被删除.

任何帮助将非常感谢,
提前致谢

///编辑

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          NUMBERn"
            + ")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全局临时表不是临时对象.它们是正确的堆表.我们创建它们一次,任何会话都可以使用它们来存储仅对该会话可见的数据.

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

关键是我们不应该删除并重新创建临时表.如果您尝试将SQL Server样式逻辑移植到Oracle中,那么您应该考虑使用PL / SQL集合来维护内存中的临时数据. Find out more.

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_temp并直接填充vertical_design,理想情况下使用INSERT INTO … SELECT * FROM语句.您将需要一些预处理来将JSON数组转换为查询,但这很容易在Java或PL / SQL中实现.

对我来说,似乎确定全局临时表不适合您的方案.

“our boss or other persons persist to do something through their way,so you cannot change that”

你有什么是老板问题而不是编程问题.因此,就StackOverflow而言,它是偏离主题的.但无论如何,这里有一些建议.

要记住的关键是我们不是在谈论对某些次优架构的妥协:你的老板明确提出的建议不会在多用户环境中起作用.所以,你的选择是:

>忽略ORA-14452错误,继续投入生产,然后使用“但是你告诉我”防御,当这一切都发生了可怕的错误.这是最弱的一个.
>隐蔽地破坏全局表并实现可在多用户场景中工作的东西.这是高风险的,因为如果你破坏了实现,你就没有防御.
>跟你的老板说话.告诉他们你正在遇到ORA-14452错误,说你做了一些调查,这似乎是以这种方式使用全局临时表的一个基本问题,但显然你忽略了一些东西.然后,问他们如何解决这个问题,因为他们之前已经实现了这个问题.这可以有几种方式,也许他们有一个解决方法,也许他们会意识到这是使用全局临时表的错误方式,也许他们会告诉你迷路.无论哪种方式,这都是最好的方法:你已经将关注提升到适当的水平.

祝好运.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读