`

(转)在Oracle 数据库中的临时表用法汇总

 
阅读更多
1 语法 

  在Oracle中,可以创建以下两种临时表: 

  1) 会话特有的临时表 

  CREATE GLOBAL TEMPORARY ( ) 

  ON COMMIT PRESERVE ROWS; 

  2) 事务特有的临时表 

  CREATE GLOBAL TEMPORARY ( ) 

  ON COMMIT DELETE ROWS; 

  CREATE GLOBAL TEMPORARY TABLE MyTempTable 

  所建的临时表虽然是存在的,但是如果insert 一条记录然后用别的连接登上去select,记录是空的。   

  --ON COMMIT DELETE ROWS 说明临时表是事务指定,每次提交后ORACLE将截断表(删除全部行) 

  --ON COMMIT PRESERVE ROWS 说明临时表是会话指定,当中断会话时ORACLE将截断表。   

  2 动态创建 

  create or replace procedure pro_temp(v_col1 varchar2,v_col2 varchar2) as 

  v_num number; 

  begin 

  select count(*) into v_num from user_tables where table_name='T_TEMP';   

  --create temporary table 

  if v_num<1 then 

  execute immediate 'CREATE GLOBAL TEMPORARY TABLE T_TEMP ( 

  COL1 VARCHAR2(10), 

  COL2 VARCHAR2(10) 

  ) ON COMMIT delete ROWS'; 

  end if;   

  --insert data 
       --这里为什么不能直接写插入的INSERT语句,因为该表是动态创建的,编译时还没有该表,所以不能直接
       插入表当中,也要采取动态执行SQL的方式。
  execute immediate 'insert into t_temp values('''  v_col1  ''','''  v_col2  ''')';   

  execute immediate 'select col1 from t_temp' into v_num; 

  dbms_output.put_line(v_num); 

  execute immediate 'delete from t_temp'; 

  commit; 

  execute immediate 'drop table t_temp'; 

  end pro_temp;   

  测试:   

  15:23:54 SQL> set serveroutput on 

  15:24:01 SQL> exec pro_temp('11','22'); 

  11   

  PL/SQL 过程已成功完成。   

  已用时间: 00: 00: 00.79 

  15:24:08 SQL> desc t_temp; 

  ERROR: 

  ORA-04043: 对象 t_temp 不存在   

  3 特性和性能(与普通表和视图的比较) 

   临时表只在当前连接内有效 

  临时表不建立索引(临时表也是可以建立索引的,如果不建的话,当数据量大时可能查询效率就比较低),所以如果数据量比较大或进行多次查询时,不推荐使用 

  数据处理比较复杂的时候时表快,反之视图快点 

  在仅仅查询数据的时候建议用游标: open cursor for 'sql clause'; 

4 楼 dolphin_ygj 2009-04-13   引用
临时表管理需要注意的地方。 

  临时表相对与其他表来说,是一种比较特殊的表结构,但是,作用又比较大,Oraclee数据库若没有这种表的话,还真是不行。为了管理好这种特殊的表,我们需要注意几个细节。 

  一是要注意临时表不能永久的保存数据。只所以称为临时表,就是因为该表中的内容只是临时存在的。当一个会话或者事务结束时,该表中的内容就会被自动清空。所以,在临时表中,一般不要保存永久数据。在实务中,有个不好的操作习惯,就是有些人在测试数据库的时候,喜欢把测试的数据放在临时数据表中。其实,这是对Oralce临时数据表认识的错误。若我们在数据库中,把要测试的数据,如销售定单的内容放在数据库的临时表中的话,则在其他功能中,如要测试销售定单日报表的功能时,就会找不到相关的定单内容。因为离开特定的会话或者事务的话,临时表中的内容就会不存在了。所以,Oralce数据库中所讲的临时表不是给我们来存储测试数据的。 

  二是临时表中的数据不会备份、恢复,对其的修改也不会有任何的日志信息。若我们在操作数据库的时候,往数据库的临时表中存入了一些信息。此时突然服务器出现当机。此时,我们想通过数据库备份文件恢复数据库临时表中的内容,或者查看临时表的日志信息,都是无法实现的。也就是说,当服务器以外死机重新启动后,临时表中的内容就会被清空。在数据库的任何地方,如数据库备份文件或者日志信息中,都查不到在重新启动之前数据库临时表中保存了哪些内容,就好象根本没有对临时表进行操作一样。 

  三是临时表表空间的管理。临时表在Oraclee数据库中,也是表的一种,其也有对应的表空间。在创建临时表的时候,若我们不指定表空间的话,默认的表空间是SYSTEM。对于临时表的表空间管理的话,我们需要注意一个小的细节。若我们把临时表的表空间归属为SYSTEM的话,也就是说,在创建临时表的时候不具体指定具体的表空间,则这个默认的表空间是不能被删除的。而若我们在创建临时表表空间的时候,指定为SYSTEM以外的表空间的话,则在不需要这表空间的时候,我们可以删除。所以,为了后续管理的方便,笔者还是建议大家在创建临时表的时候,要指定表空间。 

  四是要注意一个问题,临时表只是数据是临时的,而表仍然是永久的。也就是说,当一个会话结束或者一个事务完成时,其临时表中的数据虽然删除了,但是,临时表本身仍然是存在的。也就是说。Oraclee数据库中的临时表表是全局的,只是数据是临时的。这跟SQL Server数据库系统具有比较大的区别。其实,这两个数据库在临时表的处理上有很大的不同,各有各的特色。在以后的文章中,我会专门叙述这两种数据库在临时表管理机制上的不同,欢迎大家关注。 

  五是要注意Oraclee数据库在给临时表填入数据的时候,不会对相应的记录加锁。也就是说,当在临时表上执行DML语句的操作时,不会给记录加锁,也不会将数据的变化内容写到重做(REDO)日志中。所以不能用临时表保存永久的数据,也不能对临时表进行共同的操作。这是新手在管理数据库临时表经常会碰到的问题。 

  六是临时表与普通表之间不能相互转换。在一般情况下,临时表建立后,该表就不能被转换成永久表。所以,这也说明一个道理,利用临时表作为数据库设计时候的测试表不合适。这个临时表可能跟我们按字面意思理解的临时表有误,不是我们所认为的为了测试表结构而建立的临时表。这一点是我们在刚开始接触OracleE数据库时,经常会犯的错误。 

3 楼 dolphin_ygj 2009-04-13   引用
如何使用临时表? 
5.4.1无法显示的数据设计师' style='text-decoration:underline;color:blue;' target=_blank>设计师L告诉程序员M在项目中需要使用到临时表。由于使用的是PostgreSQL数据库,L还告诉M,在PostgreSQL中使用临时表需要利用Java的JDBC来建表。 

M虽然并不理解为什么需要利用JDBC来建表,但是他深信以当前他的所知这不是一件困难的事,于是程序员M模拟了一个简单场景,对Room实体的新增和查询动作。 

M写下了如下的代码,见例5.18: 

例5.18:TestTempTableDAONoManager.java 

package dao.jdbc; 



import java.sql.Connection; 

import java.sql.DriverManager; 

import java.sql.PreparedStatement; 

import java.sql.ResultSet; 

import java.sql.SQLException; 



import entity.Room; 



public class TestTempTableDAONoManager { 

         // 针对temproom表的操作 

         private final String CREAT_ROOM_TABLE = "CREATE GLOBAL TEMP TABLE temproom" 

                            "( id int8 NOT NULL,  " 

                            "address varchar(255),  " 

                            "number varchar,  " 

                            "CONSTRAINT room_pkey PRIMARY KEY (id)) " 

                            "ON COMMIT DELETE ROWS;"; 



         private final String INSERT_ROOM_TABLE = "insert into temproom (id, address, number) values (?,?,?)"; 



         private final String FIND_ROOM_BY_KEY = "select * from temproom where id=?"; 



         //取得连接 

         private Connection getConnection() throws SQLException { 

                   try { 

                            final String url = "jdbc:postgresql://localhost/TESTDB"; 

                            final String user = "sa"; 

                            final String password = "1111"; 

                            Class.forName("org.postgresql.Driver"); 

                            Connection connection = DriverManager.getConnection(url, user, 

                                               password); 

                            return connection; 

                   } catch (ClassNotFoundException e) { 

                            throw new SQLException(e.getMessage()); 

                   } 

         } 



         //创建临时表 

         public void createTable() { 

                   // 提供一个连接 

                   Connection con = null; 

                   // 提供一个创建预编译SQL 语句的变量 

                   PreparedStatement ps = null; 



                   try { 

                            con = this.getConnection(); 

                            ps = con.prepareStatement(this.CREAT_ROOM_TABLE); 

                            ps.executeUpdate(); 

                   } catch (SQLException ex) { 

                            ex.printStackTrace(); 

                   } finally { 

                            // 必须进行的处理,关闭PreparedStatement、ResultSet、Connection 

                            try { 

                                     if (ps != null) 

                                               ps.close(); 

                                     if (con != null) 

                                               con.close(); 

                            } catch (SQLException ex) { 

                                     ex.printStackTrace(); 

                            } 

                   } 

         } 



         //插临时表 

         public void insertRoom(Room room) throws Exception { 

                   // 提供一个连接 

                   Connection con = null; 

                   // 提供一个创建预编译SQL 语句的变量 

                   PreparedStatement ps = null; 

                   // 提供一个返回SQL查询结果的ResultSet接口变量 

                   // ResultSet带有游标可以指向返回结果中的某条记录 

                   ResultSet rs = null; 

                   

                   try { 

                            // 取得JDBC连接 

                            con = this.getConnection(); 

                            // 预编译SQL语句并执行insertSql 

                            ps = con.prepareStatement(this.INSERT_ROOM_TABLE); 

                            ps.setLong(1, room.getId()); 

                            ps.setString(2, room.getAddress()); 

                            ps.setString(3, room.getNumber()); 

                            // 若新增失败 

                            if (ps.executeUpdate() != 1) { 

                                     throw new Exception("更新失败"); 

                            } 

                   } catch (SQLException ex) { 

                            ex.printStackTrace(); 

                   } finally { 

                            // 必须进行的处理,关闭PreparedStatement、ResultSet、Connection 

                            try { 

                                     if (rs != null) 

                                               rs.close(); 

                                     if (ps != null) 

                                               ps.close(); 

                                     if (con != null) 

                                               con.close(); 

                            } catch (SQLException ex) { 

                                     ex.printStackTrace(); 

                            } 

                   } 

         } 



         /** 

          * 根据Room表的主键返回Room实体 

          */ 

         public Room findRoom(Long id) { 

                   // 提供一个连接 

                   Connection con = null; 

                   // 提供一个创建预编译SQL 语句的变量 

                   PreparedStatement ps = null; 

                   // 提供一个返回SQL查询结果的ResultSet接口变量 

                   // ResultSet带有游标可以指向返回结果中的某条记录 

                   ResultSet rs = null; 

                   // 提供一个Room实体的变量 

                   Room room = null; 

                   

                   try { 

                            // 取得JDBC连接 

                            con = this.getConnection(); 



                            // 预编译SQL语句并执行findSql 

                            ps = con.prepareStatement(this.FIND_ROOM_BY_KEY); 

                            ps.setLong(1, id); 

                            rs = ps.executeQuery(); 

                            // 当返回结果集中无记录时返回null 

                            if (!rs.next()) { 

                                     return null; 

                            } 

                            // 以下的情况将保证在结果集中有记录时的应用 

                            // 创建Room实体的实例以作处理 

                            room = new Room(); 

                            room.setId(rs.getLong("id")); 

                            room.setAddress(rs.getString("address")); 

                            room.setNumber(rs.getString("number")); 

                   } catch (SQLException ex) { 

                            ex.printStackTrace(); 

                   } finally { 

                            // 必须进行的处理,关闭PreparedStatement、ResultSet、Connection 

                            try { 

                                     if (rs != null) 

                                               rs.close(); 

                                     if (ps != null) 

                                               ps.close(); 

                                     if (con != null) 

                                               con.close(); 

                            } catch (SQLException ex) { 

                                     ex.printStackTrace(); 

                            } 

                   } 

                   return room; 

         } 



         public static void main(String[] args) { 

                   TestTempTableDAONoManager testTempTableDAONoManager = new TestTempTableDAONoManager(); 

                   // 创建表temproom 

                   testTempTableDAONoManager.createTable(); 



                   // 新建Room实体 

                   Room room = new Room(); 

                   room.setId(1L); 

                   room.setNumber("001"); 

                   room.setAddress("RW Room"); 

                   try { 

                            // 插表temproom 

                            testTempTableDAONoManager.insertRoom(room); 

                   } catch (Exception ex) { 

                            ex.printStackTrace(); 

                   } 



                   // 显示结果 

                   Room showRoom = new Room(); 

                   showRoom = testTempTableDAONoManager.findRoom(1L); 

                   System.out.println("-----Room id:" showRoom.getId()); 

                   System.out.println("-----Room Address:" showRoom.getAddress()); 

                   System.out.println("-----Room Number:" showRoom.getNumber()); 

         } 



在这段代码中,M实现了三个主要的DAO方法: 

(1)createTable(),此方法用以创建临时表temproom 

(2)insertRoom(),此方法用以为临时表temproom插入一条记录 

(3)findRoom(),此方法用以取得insertRoom()方法所插入的一条,将以Room实体返回。 

此外,为了简单起见,M给出了getConnection()方法,三个DAO的主要方法都将调用getConnection()来取得数据库的JDBC连接。 

很快代码实现了,于是M又构造了main()方法来对实现结果做测试。当M满心欢喜的以为结果将如他所料时,一个意想不到的情况发生了。这段看起来完全正确的代码居然抛出了异常: 

java.sql.SQLException: ERROR: relation "temproom" does not exist 

这是怎么一回事呢? 

5.4.2 理解临时表M的代码如果用在与非临时表的表交互时自然没有错,但是用在临时表上显然就错了。原因就出在临时表上。要解决这个“无法显示的数据”问题,就必须搞清楚什么是临时表。 

绝大多数关系型数据库都有临时表,这在SQL-92中也是一个标准。临时表的特性在于分布式运用,也即任何一个用户连接到数据库,即使使用的是同名的临时表,这个用户的所有操作也对另一连接的用户不可见。换句话说,就是“临时表多用户并行不是问题”。 

在标准的SQL-92中,临时表的定义是这样的: 

(1)使用CREATE TEMPORARY TABLE…定义临时表。 

(2)定义临时表的结尾部分可以存在ON COMMIT DELETE ROWS子句或ON COMMIT PRESERVE ROWS子句。 

(3)若缺省ON COMMIT子句的情况下,将使用ON COMMIT DELETE ROWS子句所提供的行为。 

通过ON COMMIT DELETE ROWS子句定义的临时表它的特性在于:“临时表的所有数据将在一次事务提交后被全部删除” 

通过ON COMMIT PRESERVE ROWS子句定义的临时表它的特性在于:“临时表的所有数据在一次事务提交后将依旧保留” 

但是无论使用哪种ON COMMIT子句定义的临时表,它在一次数据库连接结束后都将被删除所有数据。 

请注意:一次数据库连接和一次事务提交是两个概念,前者读者可以简单的理解为Connection连接的关闭,也即Java中“connection.close()”方法的调用;后者读者可以理解为Connection连接中的事务提交,也即Java中“connection.commit()”方法的调用。 

每一种数据库对于临时表的定义都存在着兼容性的问题,在SQL-92编码规则中临时表创建后即使连接结束也不会被drop(不是DELETE)掉,符合这个标准的数据库具有代表性的就是Oracle,但是有些数据库则定义临时表在连接结束后将连同整个表都会被drop掉,PostgreSQL就是其中的一种,MySQL也是如此。因此若要使用临时表,则必须在项目启动后对该项目所使用的数据库文档进行必要的了解。 

由于临时表的先天特性(多用户并行无关性),在项目中使用临时表是很常见的。 

如何使用临时表?(二) 分类:我的著作2008.1.3 14:31 作者:小仙狗 | 评论:0 | 阅读:660 
5.4.3 查找问题在理解了临时表的相关特性后,不难看出 M的代码所存在的问题。 

(1)首先,L要求M使用JDBC来创建临时表的Schema是没有问题的,由于PostgreSQL每次连接结束都将drop临时表,因此必须手动创建临时表(调用createTable())。 

(2)M在这段代码中最大的问题在于getConnection(),在例5.18中可以看到任何一个DAO方法都会调用getConnection(),而每个DAO方法的finally部分又会关闭Connection。这样的话,客户端在调用createTable()方法结束后已经关闭了数据库连接。按照临时表的特性,此时临时表中的数据已经被自动删除了。 

5.4.4 提供一个ConnectionManager问题(2)是整段代码引起错误的主要原因,解决这个问题有多种方案。最容易想到的就是整个DAO全局共享一个Connection,可是如果就简单的提供一个单例类是有问题的。 

(1)因为临时表本身的特性虽然是多用户并行无关性,但是这个无关性的前提是每个用户一个连接。假设提供一个单例类,那么在整个运行期所有客户端都将使用这个Connection,如此的结果必然导致多个客户共用一个Connection。 

(2)对于Connection连接提供单例类,必然导致一个长连接不被释放,对于任何一个系统来说这都是无法接受的。 

有鉴于此,单例类的实现被否定了。深入的再想一下,不难发现,其实对于临时表的操作需要的是以下两个条件: 

(1)提供一种方式,让多个操作临时表的方法共享一个连接。 

(2)而这样一个连接对于任何请求都将是独立的。 

假设仅以J2EE模型来说,这是很容易实现的。因为从Servlet请求到来的每一个客户端都只发生在自己的线程中。这就给实现两个条件带来了契机,只需要利用Java的ThreadLocal类。 

提供一个ConnectionManager类,该类将使用ThreadLocal类来管理Connection连接,以保证该Connection连接对于一次请求的线程是独立的。请见例5.19: 

例5.19:ConnectionManager.java 

package dao.jdbc; 



import java.sql.Connection; 



public class ConnectionManager { 

         //静态变量"当前线程",用以管理Connection 

         private static final ThreadLocal currentConnection = new ThreadLocal(); 



         //静态方法取得"当前线程"所使用的Connection 

         public static Connection getConnection() { 

                   return (Connection)currentConnection.get(); 

         } 



         //将"当前线程"与"当前连接"绑定 

         static Connection setCurrentConnection(Connection connection) { 

                   Connection priorConnection = (Connection)currentConnection.get(); 

                   currentConnection.set(connection); 

                   return priorConnection; 

         } 





客户端只需要在每次请求到来时取得一个Connection连接,调用setCurrentConnection()方法,将Connection连接与当前线程绑定,而DAO中的每个方法都调用getConnection()方法来获取当前线程绑定的Connection连接,在DAO的每个方法中finally时不应该关闭Connection连接,将关闭的动作交给客户端处理。 

5.4.5 不能被忽略的ON COMMIT DELETE ROWS仅利用ConnectionManager.java还是不能完全结束工作,因为临时表的ON COMMIT DELETE ROWS子句的本意是“临时表的所有数据将在一次事务提交后被全部删除”。 

在JDBC的Connection连接中事务本身是被设置为AutoCommit的,这意味着要想在“创表->插表->查表”三个动作结束后才提交事务,那势必要设置AutoCommit为false。否则在第二个动作“插表”的行为结束时事务就已经提交了,即使Connection连接依然保持,但临时表还是会将所有数据在这次事务提交后全部删除。正确的客户端操作如下: 

//取得绑定的连接 

Connection con = ConnectionManager.getConnection(); 

//设置AutoCommit为false 

con.setAutoCommit(false); 

//实现DAO方法中与临时表相关的操作 

… 

//提交事务 

con.commit(); 

//还原AutoCommit 

con.setAutoCommit(true); 

以上可以完全操控临时表了。 

5.4.6 被改写的完整代码以下将对M的代码进行改写,请读者注意该段代码中加粗的部分。请见例5.20: 

例5.20:TestTempTableDAO.java 

package dao.jdbc; 



import java.sql.Connection; 

import java.sql.DriverManager; 

import java.sql.PreparedStatement; 

import java.sql.ResultSet; 

import java.sql.SQLException; 



import entity.Room; 



public class TestTempTableDAO { 

         // 针对temproom表的操作 

         private final String CREAT_ROOM_TABLE = "CREATE GLOBAL TEMP TABLE temproom" 

                            "( id int8 NOT NULL,  " 

                            "address varchar(255),  " 

                            "number varchar,  " 

                            "CONSTRAINT room_pkey PRIMARY KEY (id)) " 

                            "ON COMMIT DELETE ROWS"; 



         private final String INSERT_ROOM_TABLE = "insert into temproom (id, address, number) values (?,?,?)"; 



         private final String FIND_ROOM_BY_KEY = "select * from temproom where id=?"; 



         public void createTable() { 

                   // 提供一个连接 

                   Connection con = null; 

                   // 提供一个创建预编译SQL 语句的变量 

                   PreparedStatement ps = null; 



                   try { 

              //取得绑定的连接 

                            con = ConnectionManager.getConnection(); 

                            ps = con.prepareStatement(this.CREAT_ROOM_TABLE); 

                            ps.executeUpdate(); 

                   } catch (SQLException ex) { 

                            ex.printStackTrace(); 

                   } finally { 

                            // 必须进行的处理,关闭PreparedStatement、ResultSet 

                            try { 

                                     if (ps != null) 

                                               ps.close(); 

                                     // 请注意不用关闭Connection,否则无法实现连接的传递 

                                     /* 

                                      * if (con != null) con.close(); 

                                      */ 

                            } catch (SQLException ex) { 

                                     ex.printStackTrace(); 

                            } 

                   } 

         } 



         public void insertRoom(Room room) throws Exception { 

                   // 提供一个连接 

                   Connection con = null; 

                   // 提供一个创建预编译SQL 语句的变量 

                   PreparedStatement ps = null; 

                   // 提供一个返回SQL查询结果的ResultSet接口变量 

                   // ResultSet带有游标可以指向返回结果中的某条记录 

                   ResultSet rs = null; 



                   try { 

              //取得绑定的连接 

                            con = ConnectionManager.getConnection(); 

                            // 预编译SQL语句并执行insertSql 

                            ps = con.prepareStatement(this.INSERT_ROOM_TABLE); 

                            ps.setLong(1, room.getId()); 

                            ps.setString(2, room.getAddress()); 

                            ps.setString(3, room.getNumber()); 

                            // 若新增失败 

                            if (ps.executeUpdate() != 1) { 

                                     throw new Exception("更新失败"); 

                            } 

                   } catch (SQLException ex) { 

                            ex.printStackTrace(); 

                   } finally { 

                            // 必须进行的处理,关闭PreparedStatement、ResultSet 

                            try { 

                                     if (rs != null) 

                                               rs.close(); 

                                     if (ps != null) 

                                               ps.close(); 

                                     // 请注意不用关闭Connection,否则无法实现连接的传递 

                                     /* 

                                      * if (con != null) con.close(); 

                                      */ 

                            } catch (SQLException ex) { 

                                     ex.printStackTrace(); 

                            } 

                   } 

         } 



         /** 

          * 根据Room表的主键返回Room实体 

          */ 

         public Room findRoom(Long id) { 

                   // 提供一个连接 

                   Connection con = null; 

                   // 提供一个创建预编译SQL 语句的变量 

                   PreparedStatement ps = null; 

                   // 提供一个返回SQL查询结果的ResultSet接口变量 

                   // ResultSet带有游标可以指向返回结果中的某条记录 

                   ResultSet rs = null; 

                   // 提供一个Room实体的变量 

                   Room room = null; 

                   

                   try { 

              //取得绑定的连接 

                            con = ConnectionManager.getConnection(); 



                            // 预编译SQL语句并执行findSql 

                            ps = con.prepareStatement(this.FIND_ROOM_BY_KEY); 

                            ps.setLong(1, id); 

                            rs = ps.executeQuery(); 

                            // 当返回结果集中无记录时返回null 

                            if (!rs.next()) { 

                                     return null; 

                            } 

                            // 以下的情况将保证在结果集中有记录时的应用 

                            // 创建Room实体的实例以作处理 

                            room = new Room(); 

                            room.setId(rs.getLong("id")); 

                            room.setAddress(rs.getString("address")); 

                            room.setNumber(rs.getString("number")); 

                   } catch (SQLException ex) { 

                            ex.printStackTrace(); 

                   } finally { 

                            // 必须进行的处理,关闭PreparedStatement、ResultSet、Connection 

                            try { 

                                     if (rs != null) 

                                               rs.close(); 

                                     if (ps != null) 

                                               ps.close(); 

                                     // 请注意不用关闭Connection,否则无法实现连接的传递 

                                     /* 

                                      * if (con != null) con.close(); 

                                      */ 

                            } catch (SQLException ex) { 

                                     ex.printStackTrace(); 

                            } 

                   } 

                   return room; 

         } 



         public static void main(String[] args) { 



                   try { 

                            //绑定连接的代码不应该存在于这里,但是为了测试方便依然放在了这里 

                            final String url = "jdbc:postgresql://localhost/TESTDB"; 

                            final String user = "sa"; 

                            final String password = "1111"; 

                            Class.forName("org.postgresql.Driver"); 

                            Connection connection = DriverManager.getConnection(url, user, 

                                               password); 

                            //设置AutoCommit为false 

                            connection.setAutoCommit(false); 

                            //绑定连接 

                            ConnectionManager.setCurrentConnection(connection); 

                            

                            TestTempTableDAO testTempTableDAO = new TestTempTableDAO(); 

                            // 创建表temproom 

                            testTempTableDAO.createTable(); 



                            // 新建Room实体 

                            Room room = new Room(); 

                            room.setId(1L); 

                            room.setNumber("001"); 

                            room.setAddress("RW Room"); 

                            // 插表temproom 

                            testTempTableDAO.insertRoom(room); 



                            // 显示结果 

                            Room showRoom = new Room(); 

                            showRoom = testTempTableDAO.findRoom(1L); 

                            

                            //提交事务 

                            connection.commit(); 

                            //还原AutoCommit 

                            connection.setAutoCommit(true); 

                            System.out.println("-----Room id:" showRoom.getId()); 

                            System.out.println("-----Room Address:" showRoom.getAddress()); 

                            System.out.println("-----Room Number:" showRoom.getNumber()); 

                   } catch (ClassNotFoundException e) { 

                            e.printStackTrace(); 

                   } catch (Exception ex) { 

                            ex.printStackTrace(); 

                   } 

         } 



2 楼 dolphin_ygj 2009-04-13   引用
在Hibernate 3中提供了&lt;subselect&gt;功能。 
大家留意(20)项: 
&lt;class 
        name="ClassName"                              (1) 
        table="tableName"                             (2) 
        discriminator-value="discriminator_value"     (3) 
        mutable="true|false"                          (4) 
        schema="owner"                                (5) 
        catalog="catalog"                             (6) 
        proxy="ProxyInterface"                        (7) 
        dynamic-update="true|false"                   (8) 
        dynamic-insert="true|false"                   (9) 
        select-before-update="true|false"             (10) 
        polymorphism="implicit|explicit"              (11) 
        where="arbitrary sql where condition"         (12) 
        persister="PersisterClass"                    (13) 
        batch-size="N"                                (14) 
        optimistic-lock="none|version|dirty|all"      (15) 
        lazy="true|false"                             (16) 
        entity-name="EntityName"                      (17) 
        check="arbitrary sql check condition"         (18) 
        rowid="rowid"                                 (19) 
        subselect="SQL expression"                    (20) 
        abstract="true|false"                         (21) 
        node="element-name" 
/&gt; 
     在(20)中注明,subselect 是可选的,提供一个不变、只读的实体到数据库子查询的映射。在需要一个视图而不是基本表,却不需要在数据库建立这个视图时适用。 
     可以看到,这个&lt;subselect&gt;是适合对基本表中的数据进行查询、统计的。在在一些统计页面时极为有用。 
   下面是Hibernate Doc中提供的例子: 
  &lt;class name="Summary"&gt; 
    &lt;subselect&gt; 
        select item.name, max(bid.amount), count(*) 
        from item 
        join bid on bid.item_id = item.id 
        group by item.name 
    &lt;/subselect&gt; 
    &lt;synchronize table="item"/&gt; 
    &lt;synchronize table="bid"/&gt; 
    &lt;id name="name"/&gt; 
    ... 
&lt;/class&gt; 
    我们的一个项目中,需要管理n个项目,其中有一个页面,需要统计、计算这些项目中的一些属性,刚开始时是使用从基本表中取出数据,然后在一个类文件中计算出页面的值,计算又包括了三个比较大的循环。在开发时没有问题,但是在实际投入使用时发现页面载入极慢,大量时间花费在这些项目的统计、计算了。 
   在收到bug反馈后,我们对统计页面视图进行设计,专门设计出一个映射文件用于计算数据(同上面的例子),把数据的计算、统计等都放到数据库中进行,比较发现大大加快了页面的显示速度。大约快了约40~50%。 
  一点经验,呵呵,不知对楼主有用否?
1 楼 dolphin_ygj 2009-04-13   引用
Oracle临时表 优化查询速度 
1、前言 
    目前所有使用Oracle作为数据库支撑平台的应用,大部分数据量比较庞大的系统,即表的数据量一般情况下都是在百万级以上的数据量。当然在Oracle中创建分区是一种不错的选择,但是当你发现你的应用有多张表关联的时候,并且这些表大部分都是比较庞大,而你关联的时候发现其中的某一张或者某几张表关联之后得到的结果集非常小并且查询得到这个结果集的速度非常快,那么这个时候我考虑在Oracle中创建“临时表”。 
    我对临时表的理解:在Oracle中创建一张表,这个表不用于其他的什么功能,主要用于自己的软件系统一些特有功能才用的,而当你用完之后表中的数据就没用了。Oracle的临时表创建之后基本不占用表空间,如果你没有指定临时表(包括临时表的索引)存放的表空的时候,你插入到临时表的数据是存放在ORACLE系统的临时表空间中(TEMP)。 
2、临时表的创建 
    创建Oracle临时表,可以有两种类型的临时表:会话级的临时表和事务级的临时表。 


    1)会话级的临时表因为这这个临时表中的数据和你的当前会话有关系,当你当前SESSION不退出的情况下,临时表中的数据就还存在,而当你退出当前SESSION的时候,临时表中的数据就全部没有了,当然这个时候你如果以另外一个SESSION登陆的时候是看不到另外一个SESSION中插入到临时表中的数据的。即两个不同的SESSION所插入的数据是互不相干的。 

当某一个SESSION退出之后临时表中的数据就被截断(truncate table,即数据清空)了。 



会话级的临时表创建方法: 

Create Global Temporary Table Table_Name(Col1 Type1,Col2 Type2...) On Commit Preserve Rows;举例create global temporary table Student(Stu_id Number(5),Class_id  Number(5),Stu_Name Varchar2(8),Stu_Memo varchar2(200)) on Commit Preserve Rows ; 


    2)事务级临时表是指该临时表与事务相关,当进行事务提交或者事务回滚的时候,临时表中的数据将自行被截断,其他的内容和会话级的临时表的一致(包括退出SESSION的时候,事务级的临时表也会被自动截断)。 



事务级临时表的创建方法: 

Create Global Temporary Table Table_Name(Col1 Type1,Col2 Type2...) On Commit Delete Rows; 



举例: 

create global temporary table Classes(Class_id Number(5),Class_Name Varchar2(8),Class_Memo varchar2(200)) on Commit delete Rows ; 


    3)、两种不通类型的临时表的区别: 

            语法上,会话级临时表采用on commit preserve rows而事务级则采用on commit delete rows; 

            用法上,会话级别只有当会话结束临时表中的数据才会被截断,而且事务级临时表则不管是commit、rollback或者是会话结束,临时表中的数据都将被截断。 


3、例子: 

    1)、会话级(Session关闭掉之后数据就没有了,当Commit的时候则数据还在,当Rollback的时候则数据也是一样被回滚): 
     insert into student(stu_id,class_id,stu_name,stu_memo) values(1,1,'张三','福建'); 
     insert into student(stu_id,class_id,stu_name,stu_memo) values(2,1,'刘德华','福州'); 
     insert into student(stu_id,class_id,stu_name,stu_memo) values(3,2,'S.H.E','厦门'); 
SQL> select *from student ; 

STU_ID CLASS_ID STU_NAME STU_MEMO 
------ -------- -------- -------------------------------------------------------------------------------- 
     1        1 张三     福建 
     2        1 刘德华   福州 
     3        2 S.H.E    厦门 
     4        2 张惠妹   厦门 

SQL> commit; 

Commit complete 

SQL> select * from student ; 

STU_ID CLASS_ID STU_NAME STU_MEMO 
------ -------- -------- -------------------------------------------------------------------------------- 
     1        1 张三     福建 
     2        1 刘德华   福州 
     3        2 S.H.E    厦门 
     4        2 张惠妹   厦门 

SQL>insert into student(stu_id,class_id,stu_name,stu_memo) values(4,2,'张惠妹','厦门'); 

1 row inserted 

SQL> select * from student ; 

STU_ID CLASS_ID STU_NAME STU_MEMO 
------ -------- -------- -------------------------------------------------------------------------------- 
     1      &nbsp; 1 张三     福建 
     2        1 刘德华   福州 
     3        2 S.H.E    厦门 
     4        2 张惠妹   厦门 
     4        2 张惠妹   厦门 



SQL> rollback ; 

Rollback complete 

SQL> select * from student ; 

STU_ID CLASS_ID STU_NAME STU_MEMO 
------ -------- -------- -------------------------------------------------------------------------------- 
     1        1 张三     福建 
     2        1 刘德华   福州 
     3        2 S.H.E    厦门 
     4        2 张惠妹   厦门 

SQL> 
    2)、事务级(Commit之后就删除数据):本例子将采用以下的数据: 
      insert into classes(Class_id,Class_Name,Class_Memo) values(1,'计算机','9608'); 
      insert into classes(Class_id,Class_Name,Class_Memo) values(2,'经济信息','9602'); 
      insert into classes(Class_id,Class_Name,Class_Memo) values(3,'经济信息','9603'); 
  在一个SESSION中(比如SQLPLUS登陆)插入上面3条记录,然后再以另外一个SESSION(用SQLPLUS再登陆一次)登陆,当你select * from classes;的时候,classes表是空的,而你再第一次登陆的SQLPLUS中select的时候可以查询到,这个时候你没有进行commit或者rollback之前你可以对刚才插入的3条记录进行update、delete等操作,当你进行commit或者rollback的时候,这个时候由于你的表是事务级的临时表,那么在插入数据的session也看不到数据了,这个时候数据就已经被截断了。 
     运行结果如下: 
SQL> insert into classes(Class_id,Class_Name,Class_Memo) values(1,'计算机','9608'); 

1 row inserted 

SQL> insert into classes(Class_id,Class_Name,Class_Memo) values(2,'经济信息','9602'); 

1 row inserted 

SQL> insert into classes(Class_id,Class_Name,Class_Memo) values(3,'经济信息','9603'); 

1 row inserted 

SQL> update classes set class_memo ='' where class_id=3 ; 

1 row updated 

SQL> select * from classes ; 

CLASS_ID CLASS_NAME CLASS_MEMO 
-------- ---------- -------------------------------------------------------------------------------- 
       1 计算机     9608 
       2 经济信息   9602 
       3 经济信息   

SQL> delete from classes where class_id=3 ; 

1 row deleted 

SQL> select * from classes ; 

CLASS_ID CLASS_NAME CLASS_MEMO 
-------- ---------- -------------------------------------------------------------------------------- 
       1 计算机     9608 
       2 经济信息   9602 
SQL> commit; 

Commit complete 

SQL> select *from classes ; 

CLASS_ID CLASS_NAME CLASS_MEMO 
-------- ---------- -------------------------------------------------------------------------------- 

SQL> 
再重复插入一次,然后rollback。 
SQL> Rollback ; 

Rollback complete 

SQL> select * from classes ; 

CLASS_ID CLASS_NAME CLASS_MEMO 
-------- ---------- -------------------------------------------------------------------------------- 

SQL> 

4、临时表的应用 
    1)、当某一个SQL语句关联的表在2张及以上,并且和一些小表关联。可以采用将大表进行分拆并且得到比较小的结果集合存放在临时表中。 
    2)、程序执行过程中可能需要存放一些临时的数据,这些数据在整个程序的会话过程中都需要用的等等。 
5、注意事项: 
    1)、临时表的索引以及对表的修改、删除等和正常的表是一致的。 
    2)、Oracle的临时表是Oracle8i才支持的功能特性,如果你的Oracle版本比较低的话,那么就可能没有办法用到了,如果你的Oracle版本是8i的话,你还需要把$ORACLE_HOME/admin/${ORACLE_SID}/pfile目录下的init<ORACLE_SID>.ora初始参数配置文件的compatible修改为compatible = "8.1.0",我的服务器上就是这样子配置的。当然也可以修改为compatible = "8.1.6" 

以上是我在对大表进行优化的时候采用的一些手段,效果显著。 
分享到:
评论

相关推荐

    oracle数据库经典题目

    在Oracle数据库中,数据库的操作模式分为专用服务器(DELICATED SERVER)模式和多线程服务器(MULTITHREADED SERVER)模式两种。其中,在专用服务器模式中为每个用户进程创建一个服务器进程,用户进程与服务器进程之间...

    oracle数据库dba管理手册

    第一部分 数据库体系结构 第1章 Oracle体系结构 1 1.1 数据库概述及实例 1 1.2 数据库 1 1.2.1 表空间 2 1.2.2 文件 2 1.3 实例 3 1.4 数据库内部结构 3 1.4.1 表、列和数据类型 4 1.4.2 约束条件 5 1.4.3 抽象数据...

    ORACLE11G宝典.rar 是光盘里面的内容,书太厚咧没法影印啊

     《Oracle11g宝典》是Oracle数据库管理员、安全管理员、网络管理员、应用开发人员的参考指南,还是Oracle技术支持和培训机构、Oracle学习班、高等院校计算机专业数据库课程的参考教材和上机指导教材。每类人员都...

    Oracle SQL高级编程(资深Oracle专家力作,OakTable团队推荐)--随书源代码

    有近20年使用Oracle技术产品以及Oracle数据库管理员/Oracle数据库应用管理员的经验,是真正应用集群、性能调优以及数据库内部属性方面的专家。同时是一位演讲家及Oracle ACE。  JARED STILL 从1994年就开始使用...

    (银行卡)数据库设计报告.doc

    物理设计 7 5.1 表汇总 7 5.2 公告表 7 5.2.1外键表 8 5.3部门表 8 5.4角色表 8 5.4.1角色设置 9 5.4.2权限设置 9 5.5操作员表 10 5.5.1外键表 10 5.6菜单表 10 5.7导入数据临时表 11 5.7.1外键表 12 5.8导入数据...

    Toad 使用快速入门

     注意,如果是选择了专门建立toad这个用户的话,需要先修改一下脚本,指定用户的默认表空间和临时表空间。 需要使用Oracle8i 的Profile analyzer,必须运行ToadProfiler.sql  需要加强Toad的安全性,必须...

    SQL21日自学通

    在子查询中使用汇总函数140 子查询的嵌套141 相关子查询144 EXISTS ANY ALL 的使用147 总结151 问与答151 校练场152 练习153 第一周回顾154 预览154 第二周概貌155 这一周都讲些什么155 第八天操作数据156 目标...

    Java开发实战1200例(第1卷).(清华出版.李钟尉.陈丹丹).part3

    实例133 使用方法实现线程同步 172 实例134 使用代码块实现线程同步 174 实例135 使用特殊域变量实现线程同步 175 实例136 使用重入锁实现线程同步 176 实例137 使用线程局部变量实现线程同步 177 实例138 简单的...

    asp.net知识库

    可按任意字段排序的分页存储过程(不用临时表的方法,不看全文会后悔) 常用sql存储过程集锦 存储过程中实现类似split功能(charindex) 通过查询系统表得到纵向的表结构 将数据库表中的数据生成Insert脚本的存储过程!!! ...

    C#程序开发范例宝典(第2版).part08

    实例011 在状态栏中显示检查框 9 实例012 带进度条的状态栏 10 实例013 状态栏中加入图标 11 1.4 导航菜单界面 11 实例014 OutLook界面 11 实例015 带导航菜单的主界面 12 实例016 图形化的导航界面 14 1.5 ...

    C#程序开发范例宝典(第2版).part13

    实例011 在状态栏中显示检查框 9 实例012 带进度条的状态栏 10 实例013 状态栏中加入图标 11 1.4 导航菜单界面 11 实例014 OutLook界面 11 实例015 带导航菜单的主界面 12 实例016 图形化的导航界面 14 1.5 ...

    C#程序开发范例宝典(第2版).part02

    实例011 在状态栏中显示检查框 9 实例012 带进度条的状态栏 10 实例013 状态栏中加入图标 11 1.4 导航菜单界面 11 实例014 OutLook界面 11 实例015 带导航菜单的主界面 12 实例016 图形化的导航界面 14 1.5 ...

Global site tag (gtag.js) - Google Analytics