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 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(); } } } }
临时方面是数据在一个事务或一个会话之外不是持久的.关键的实现细节是将数据写入临时表空间而不是永久表空间.但是,数据仍然写入磁盘并从磁盘读取,因此使用全局临时表会产生显着的开销.
关键是我们不应该删除并重新创建临时表.如果您尝试将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错误,说你做了一些调查,这似乎是以这种方式使用全局临时表的一个基本问题,但显然你忽略了一些东西.然后,问他们如何解决这个问题,因为他们之前已经实现了这个问题.这可以有几种方式,也许他们有一个解决方法,也许他们会意识到这是使用全局临时表的错误方式,也许他们会告诉你迷路.无论哪种方式,这都是最好的方法:你已经将关注提升到适当的水平.
祝好运.