Z(jin)辑ֈq种目的Q我们需要用Oracle临时表(q是其中一U解x案)(j)?/p>
Oracle数据库除?jin)可以保存永久表外,q可以徏立(f)时表temporary tables。Oracle临时表分Z(x)话临时表(ON COMMIT PRESERVE ROWSQ和事务U(f)时表QON COMMIT DELETE ROWSQ?a >tb?x)话U(f)时表是指临时表中的数据只在会(x)话生命周期之中存在,当用户退Z(x)话结束的时候,Oracle自动清除临时表中数据?/p>
事务U(f)时表是指临时表中的数据只在事务生命周期中存在。当一个事务结束(commit or rollbackQ,Oracle自动清除临时表中数据。(f)时表中的数据只对当前Session有效Q每个Session都有自己的(f)时数据,q且不能讉K其它Session的(f)时表中的数据?/p>
//在数据库建立一个(f)时表Q?/strong>
- CREATE GLOBAL TEMPORARY TABLE ESPS.ESPS_EMP_RANK_TEMP
- (
- COM VARCHAR2(20 BYTE),
- EMPNO VARCHAR2(20 BYTE),
- EMPNAME VARCHAR2(100 BYTE),
- DEPTNAME VARCHAR2(300 BYTE),
- AMOUNT NUMBER,
- APPROVED_AMOUNT NUMBER,
- FOLDING_AMOUNT NUMBER,
- BENEFIT NUMBER,
- EXECUTED_RATE NUMBER,
- FOLDING_RANK NUMBER,
- BENEFIT_RANK NUMBER,
- RANK NUMBER,
- TOTAL_RANK NUMBER
- )
- //ON COMMIT PRESERVE ROWS --q里代表的是事务U(f)时表
- ON COMMIT PRESERVE ROWS --q里代表的是?x)话U(f)时表
在实际的操作中,我就验证q上面所说的。一开始我使用?jin)事务临时表,数据插入到临时表时Q用commit操作Q结果(f)时表的内Ҏ(gu)IZ(jin)。例如是QINSERT INTO ESPS_EMP_RANK_TEMP select * from tableQcommintQ执行这两段SQL后,相当于没有插入数据?/p>
如果我们使用?x)话U(f)时表Q即使用了(jin)commitQ(f)时表中的内容q是存在的。直C(x)话断开Ӟ临时表中的内Ҏ(gu)真正的清I。所以,在实际的开发过E中Q我们因该结合场景,使用不同cd的(f)时表?/p>
在徏议提案系l开发的q程中,我用了(jin)?x)话U的临时表。将查询的数据插入到临时表中Qƈ且读取(f)时表的内容,?x)话断开Ӟ临时表中的内容自动清I?nbsp;
在C#里面调用的三大步骤:(x)
//C#里面定义的一个Stringcd的变量,存储一D动态SQLQ存储过Eؓ(f)Q?/p>
- ESPS_EMP_RANK_STATISTIS({0},'{1}')
- public static string I_EMP_RANK_STATISTIS = "BEGIN ESPS_EMP_RANK_STATISTIS({0},'{1}'); END;";
//执行存储q程Q把l果集插入到临时表ESPS_EMP_RANK_TEMP
- WAF.COM.Core.OracleHelper. ExecuteNonQuery(conn, CommandType.Text, string.Format(SqlCollector.I_EMP_RANK_STATISTIS, 2,’2011’));
//d临时表中保存的结果集
- Oracle DataReader dr = WAF.COM.Core.OracleHelper. ExecuteReader(“select * from ESPS_EMP_RANK_TEMP”)
关于Oracle临时表在实际开发中的应用的相关知识׃l到q里?jin),希望本次介绍能够?gu)有所收获Q?/p>
1.?/strong>
Oracle数据库除?jin)可以保存永久表外,q可以徏立(f)时表temporary tables。这些(f)时表用来保存?sh)个会(x)话SESSION的数据,或者保存在一个事务中需要的数据。当?x)话退出或者用h交commit和回滚rollback事务的时候,临时表的数据自动清空Q但是(f)时表的结构以?qing)元数据q存储在用户的数据字怸?/p>
2.详细介绍
Oracle临时?/strong>分ؓ(f)?x)话U(f)时表和事务临时表?/p>
?x)话U(f)时表是指临时表中的数据只在会(x)话生命周期之中存在,当用户退Z(x)话结束的时候,Oracle自动清除临时表中数据?/p>
事务U(f)时表是指临时表中的数据只在事务生命周期中存在。当一个事务结束(commit or rollbackQ,Oracle自动清除临时表中数据?/p>
临时表中的数据只对当前Session有效Q每个Session都有自己的(f)时数据,q且不能讉K其它Session的(f)时表中的数据。因此,临时表不需要DML锁?/p>
当一个会(x)话结?用户正常退?用户不正帔R?ORACLE实例崩溃)或者一个事务结束的时候,Oracle对这个会(x)话的表执?TRUNCATE 语句清空临时表数?但不?x)清I其它会(x)话(f)时表中的数据. 你可以烦(ch)引(f)时表和在临时表基上徏立视?同样,建立在(f)时表上的索引也是临时?也是只对当前?x)话或者事务有? 临时表可以拥有触发器. 3.建立临时?/strong> 临时表的定义Ҏ(gu)有会(x)话SESSION都是可见?但是表中的数据只对当前的?x)话或者事务有? 建立Ҏ(gu)Q?/p> ?x)?Q?/p> ?x)?Q?/p> ?x)?看不见会(x)?中(f)时表的数据?/p>
4.Oracle临时表和SQL Server临时表异?/strong> SQL Server也可以创Z(f)时表。(f)时表与永久表怼Q但临时表存储在tempdb中,当不再用时?x)自动删除?/p>
有本地和全局两种cd的(f)时表Q二者在名称、可见性和可用性上均不相同。本C(f)时表的名UC单个数字W号 (#) 打头Q它们仅对当前的用户q接是可见的Q当用户?Microsoft SQL Server实例断开q接时被删除。全局临时表的名称以数学符?(##) 打头Q创建后对Q何用户都是可见的Q当所有引用该表的用户?SQL Server 断开q接时被删除?/p>
SQL 语句使用 CREATE TABLE 语句中ؓ(f) table_name 指定的名U引用(f)时表Q?/p> 如果本地临时表由存储q程创徏或由多个用户同时执行的应用程序创建,?SQL Server 必须能够区分׃同用户创建的表。ؓ(f)此,SQL Server 在内部ؓ(f)每个本地临时表的表名q加一个数字后~。存储在 tempdb 数据库的 sysobjects 表中的(f)时表Q其全名?CREATE TABLE 语句中指定的表名和系l生成的数字后缀l成。ؓ(f)?jin)允许追加后~Qؓ(f)本地临时表指定的表名 table_name 不能过116 个字W?/p>
除非使用 DROP TABLE 语句昑ּ除去临时表,否则临时表将在退出其作用域时ql自动除去:(x) 当存储过E完成时Q将自动除去在存储过E中创徏的本C(f)时表。由创徏表的存储q程执行的所有嵌套存储过E都可以引用此表。但调用创徏此表的存储过E的q程无法引用此表?/p>
所有其它本C(f)时表在当前会(x)话结束时自动除去?/p>
全局临时表在创徏此表的会(x)话结束且其它d停止对其引用时自动除厅RQ务与表之间的兌只在单个 Transact-SQL 语句的生存周期内保持。换a之,当创建全局临时表的?x)话l束Ӟ最后一条引用此表的Transact-SQL语句完成后,自动除L表?/p>
例如Q如果创建名?employees 的表Q则M人只要在数据库中有用该表的安全权限可以用该表,除非它已删除。如果创建名?#employees 的本C(f)时表Q只有?zhn)能对该表执行操作且在断开q接时该表删除。如果创建名?##employees 的全局临时表,数据库中的Q何用户均可对该表执行操作。如果该表在(zhn)创建后没有其他用户使用Q则当?zhn)断开q接时该表删除。如果该表在(zhn)创建后有其他用户用,?SQL Server在所有用h开q接后删除该表?/p>
在存储过E或触发器中创徏的本C(f)时表与在调用存储q程或触发器之前创徏的同名(f)时表不同。如果查询引用(f)时表Q而同时有两个同名的(f)时表Q则不定义针对哪个表解析该查询?a >tb嵌套存储q程同样可以创徏与调用它的存储过E所创徏的(f)时表同名的(f)时表。嵌套存储过E中对表名的所有引用都被解释ؓ(f)是针对该嵌套q程所创徏的表Q例如:(x) 下面是结果集Q?/p> 当创建本地或全局临时表时QCREATE TABLE 语法支持?FOREIGN KEY U束以外的其它所有约束定义。如果在临时表中指定 FOREIGN KEY U束Q该语句返回警告信息,指出此约束已被忽略,表仍?x)创建,但不h FOREIGN KEY U束。在 FOREIGN KEY U束中不能引用(f)时表?/p>
考虑使用表变量而不使用临时表。当需要在临时表上昑ּ地创建烦(ch)引时Q或多个存储q程或函数需要用表值时Q(f)时表很有用。通常Q表变量提供更有效的查询处理?/p>
和Oracle的不同点Q?/strong> 1. SQL Server临时表是一U?#8221;内存?#8221;,tb表是存储在内存(sh)?ORACLE临时表除非执行DROP TABLE,否则表定义会(x)保留在数据字怸?/p>
2. SQL Server临时表不存在cMORACLE临时表事务别上的功能?/p>
3.SQL Server本地临时?#) ?ORACLE的会(x)话别(f)时表cM,但是在会(x)话退出的时?ORACLE不会(x)删除表?/p>
4.SQL Server的全局临时?##) 是指多个q接׃n同一片内?当没有指针引用该内存区域?SQL Server自动释放全局临时表?/p>
5.׃Oracle不是一U内存(sh)的数据库. 所以如果OraclecMSQL Server 频繁的对临时表进行徏立和删除,必定?x)?jing)响性能.所以Oracle?x)保留?f)时表的定义直到用户DROP TABLE?/p>
6.在Oracle?如果需要多个用户共享一个表(cMSQL Server的全局临时?#).则可以利用永久表,q且在表中添加一些可以唯一标识用户的列.利用触发器和视图.当用户退出的时?Ҏ(gu)该登陆用L(fng)唯一信息删除相应的表中的数据. q种Ҏ(gu)lOracle带来?jin)一定量的负载?/p>
关于Oracle临时表和SQL Server临时表的不同点对比的相关知识׃l到q里?jin),希望本次的介l能够对(zhn)有所收获Q?/p>
1 、前a
Oracle Logo
目前所有?Oracle 作ؓ(f)数据库支撑^台的应用Q大部分数据量比较庞大的pȝQ即表的数据量一般情况下都是在百万以上的数据量?/p>
当然?Oracle 中创建分区是一U不错的选择Q但是当你发C的应用有多张表关联的时候,q且q些表大部分都是比较庞大Q而你兌的时候发现其中的某一张或者某几张表关联之后得到的l果集非常小q且查询得到q个l果集的速度非常快,那么q个时候我考虑?Oracle 中创?#8220;临时?#8221;?/p>
我对临时表的理解Q在 Oracle 中创Z张表Q这个表不用于其他的什么功能,主要用于自己的Y件系l一些特有功能才用的Q而当你用完之后表中的数据没用了(jin)?Oracle 的(f)时表创徏之后基本不占用表I间Q如果你没有指定临时?包括临时表的索引)存放的表I的时候,你插入到临时表的数据是存攑֜ ORACLE pȝ的(f)时表I间? TEMP )?/p>
2 、(f)时表的创?/p>
创徏Oracle 临时表,可以有两U类型的临时表:(x)
?x)话U的临时?/p>
事务U的临时??/p>
1) ?x)话U的临时表因q个临时表中的数据和你的当前?x)话有关p,当你当前SESSION 不退出的情况下,临时表中的数据就q存在,而当你退出当前SESSION 的时候,临时表中的数据就全部没有?jin),当然q个时候你如果以另外一个SESSION 登陆的时候是看不到另外一个SESSION 中插入到临时表中的数据的。即两个不同的SESSION 所插入的数据是互不相干的。当某一个SESSION 退Z后(f)时表中的数据p截断(truncate table Q即数据清空)?jin)。会(x)话的(f)时表创徏Ҏ(gu)Q?/p>
Create Global Temporary Table Table_Name (Col1 Type1,Col2 Type2...) On Commit Preserve Rows ;
举例Q?/p>
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) 事务U(f)时表是指该(f)时表与事务相养I当进行事务提交或者事务回滚的时候,临时表中的数据将自行被截断,其他的内容和?x)话U的临时表的一?包括退出SESSION 的时候,事务U的临时表也?x)被自动截?。事务临时表的创徏Ҏ(gu)Q?/p>
Create Global Temporary Table Table_Name (Col1 Type1,Col2 Type2...) On Commit Delete Rows ;
举例Q?/p>
create global temporary table Classes (Class_id Number(5), Class_Name Varchar2(8), Class_Memo varchar2(200)) on Commit delete Rows ; 3) 两中cd临时表的区别
?x)话U(f)时表采用 on commit preserve rows ;而事务则采?on commit delete rows ;用法上,?x)话U别只有当会(x)话结束(f)时表中的数据才会(x)被截断,而且事务U(f)时表则不是 commit ?rollback 或者是?x)话l束Q?a >tb临时表中的数据都被截断
4 )什么时候用(f)时表
1 )、当某一?SQL 语句兌的表?2 张及(qing)以上Qƈ且和一些小表关联。可以采用将大表q行分拆q且得到比较?yu)的l果集合存放在(f)时表?/p>
2 )、程序执行过E中可能需要存放一些(f)时的数据Q这些数据在整个E序的会(x)话过E中都需要用的等{?/p>
3 . 例子Q略
4 .临时表的不之处
1 )不支?lob 对象Q这也许是设计者基于运行效率的考虑Q但实际应用中确实需要此功能时就无法使用临时表了(jin)?/p>
2 )不支持主外键关系
所以,׃以上原因Q我们可以自己创Z(f)时表Q以弥补 oracle 临时表的不之处
上面的都是本人经q测试的Q但下面是在|上搜烦(ch)到的Ҏ(gu)Q本人具体没有测试过Q不q觉得可行性很强,有时间测试下
创徏Ҏ(gu)Q?/p>
1 、以常规表的形式创徏临时数据表的表结构,但要在每一个表的主键中加入一?SessionID 列以区分不同的会(x)话?可以?lob 列和d?
2 、写一个用h销触发器,在用L(fng)束会(x)话的时候删除本ơ会(x)话所插入的所有记?(SessionID {于本次?x)?ID 的记?) ?/p>
3 、程序写入数据时Q要Z当前的?x)?ID(SessionID) 写入表中?/p>
4 、程序读取数据时Q只d与当前会(x)?ID 相同的记录即可?/p>
功能增强的扩展设计:(x)
1 、可以在数据表上建立一个视图,视图对记录的{选条件就是当前会(x)话的SessionID ?/p>
2 、数据表中的SessionID 列可以通过Trigger 实现Q以实现对应用层的透明性?/p>
3 、高U用户可以访问全局数据Q以实现更加复杂的功能?/p>
扩展临时表的优点Q?/p>
1 、实C(jin)与Oracle 的基于会(x)话的临时表相同的功能?/p>
2 、支持SDO_GEOMETRY {lob 数据cd?/p>
3 、支持表间的d键连接,且主外键q接也是Z?x)话的?/p>
4 、高U用户可以访问全局数据Q以实现更加复杂的功?/p>
损坏非当前联机日志:(x)
1、启动数据库Q遇到ORA-00312 or ORA-00313错误Q如:
ORA-00313: open failed for members of log group 4 of tbhread 1
ORA-00312: online log 3 thread 1: '/opt/oracle/db04/oradata/ORCL/redo03.log'
从这里我们知道日志组1的数据文件损坏或丢失?br />从报警文件可以看到更详细的信?br />2、查看V$log视图:
SQL> select group#,sequence#,archived,status from v$log;
GROUP# SEQUENCE# ARC STATUS
---------- ---------- --- ----------------
1 54 YES INACTIVE
2 55 NO CURRENT
3 53 YES INACTIVE
可以知道Q该l是非当前状态,而且已经归档?br />3、用CLEAR命o(h)重徏该日志文?br />SQL>alter database clear logfile group 3;
如果是该日志l还没有归档Q则需要用
SQL>alter database clear unarchived logfile group 3;
4、打开数据库,重新备䆾数据?br />SQL>alter database open;
说明Q?br />1)、如果损坏的是非当前的联机日志文Ӟ一般只需要clear可以重日志文gQ但是如果该数据库处于归档状态但该日志还没有归档Q就需要强行clear?br />2)、徏议clearQ特别是clear后作一ơ数据库的全备䆾?br />3)、此Ҏ(gu)适用于归档与非归档数据库?/p>
损坏当前联机日志Q?/p>
归档模式下当前日志的损坏有两U情况,
一、是数据库是正常关闭Q日志文件中没有未决的事务需要实例恢复,当前日志l的损坏可以直接用alter database clear unarchived logfile group n来重建?br />二、是日志l中有活动的事务Q数据库需要媒体恢复,日志l需要用来同步,有两U补救办?br />A. 最好的办法是通过不完全恢复,可以保证数据库的一致性,但是q种办法要求在归档方式下Qƈ且有可用的备?br />B. 通过强制性恢复,但是可能D数据库不一致?br />下面分别用来说明q两U恢复方?br />5.1.2.1 通过备䆾来恢?br />1、打开数据库,?x)遇C个类似的错误
ORA-00313: open failed for members of log group 1 of thread 1
ORA-00312: online log 1 thread 1: 'D:ORACLEORADATATESTREDO01.LOG'
ORA-27041: unable to open file
OSD-04002: unable to open file
O/S-Error: (OS 2) pȝ找不到指定的文g
2、查看V$logQ发现是当前日志
SQL> select group#,sequence#,archived,status from v$log;
GROUP# SEQUENCE# ARCHIVED STATUS
---------- ---------- -------- ----------------
1 1 NO CURRENT
2 2 YES INACTIVE
3 3 YES INACTIVE
3、发现clear不成?br />SQL> alter database clear unarchived logfile group 1;
alter database clear unarchived logfile group 1
*
ERROR at line 1:
ORA-01624: log 1 needed for crash recovery of thread 1
ORA-00312: online log 1 thread 1: 'D:ORACLEORADATATESTREDO01.LOG'
4、拷贝有效的数据库的全备份,q不完全恢复数据?br />可以采用获取最q的SCN的办法用until scn恢复或用until cnacel恢复
recover database until cancel
先选择autoQ尽量恢复可以利用的归档日志Q然后重?br />recover database until cancel
q次输入cancelQ完成不完全恢复Q也是说恢复两ơ?br />如:(x)
SQL> recover database until cancel;
Auto
……
SQL> recover database until cancel;
Cancel;
5、利用alter database open resetlogs打开数据?br />说明Q?br />1、这U办法恢复的数据库是一致的不完全恢复,?x)丢失当前联机日志中的事务数?br />2、这U方法适合于归档数据库q且有可用的数据库全备䆾?br />3、恢复成功之后,记得再做一ơ数据库的全备䆾?br />4、徏议联机日志文件一定要实现镜相在不同的盘?sh),避免q种情况的发生,因ؓ(f)M数据的丢失对于生产来说都是不容许的?/p>
如果没有备䆾Q进行强制性恢?br />1、打开数据库,?x)遇C个类似的错误
ORA-00313: open failed for members of log group 1 of thread 1
ORA-00312: online log 1 thread 1: 'D:ORACLEORADATATESTREDO01.LOG'
ORA-27041: unable to open file
OSD-04002: unable to open file
O/S-Error: (OS 2) pȝ找不到指定的文g
2、查看V$logQ发现是当前日志
SQL> select group#,sequence#,archived,status from v$log;
GROUP# SEQUENCE# ARCHIVED STATUS
---------- ---------- -------- ----------------
1 1 NO CURRENT
2 2 YES INACTIVE
3 3 YES INACTIVE
3、发现clear不成?br />SQL> alter database clear unarchived logfile group 1;
alter database clear unarchived logfile group 1
*
ERROR at line 1:
ORA-01624: log 1 needed for crash recovery of thread 1
ORA-00312: online log 1 thread 1: 'D:ORACLEORADATATESTREDO01.LOG'
4、把数据库down?br />SQL>shutdown immediate
5、在init<sid>.ora中加入如下参?br />_allow_resetlogs_corruption=TRUE
6、重新启动数据库,利用until cancel恢复
SQL>recover database until cancel;
Cancel
如果出错Q不再理?x),发?
SQL>alter database open resetlogs;
7、数据库被打开后,马上执行一个full export
8、shutdown数据?L_all_resetlogs_corrupt参数
9、重建库
10、importq完成恢?/p>
11、徏议执行一下ANALYZE TABLE ...VALIDATE STRUCTURE CASCADE;
说明Q?br />1、该恢复Ҏ(gu)是没有办法之后的恢复Ҏ(gu)Q一般情况下不要采用Q因Ҏ(gu)可能D数据库的不一?br />2、该Ҏ(gu)也丢失数据,但是丢失的数据没有上一U方法的数据多,主要是未写入数据文g的已提交或未提交数据?br />3、徏议成功后严格执行以上??1步,完成数据库的(g)查与分析
4、全部完成后做一ơ数据库的全备䆾
5、徏议联机日志文件一定要实现镜相在不同的盘?sh),避免q种情况的发生,因ؓ(f)M数据的丢失对于生产来说都是不容许的?/p>