终于以一种奇怪的方式搞定了Oracle的临时表问题

发表于:2007-07-02来源:作者:点击数: 标签:
程序中常常需要在一个主键范围内进行子查询,而这个范围是在前台中动态生成的,所以传过来的只能是一个字符串格式的确定这个主键范围的 sql 语句.以前的做法是在sp中再根据这个sql语句拼出来返回最终结果的更大的语句.发现这样子的语句往往效率很低,而且 数据

程序中常常需要在一个主键范围内进行子查询,而这个范围是在前台中动态生成的,所以传过来的只能是一个字符串格式的确定这个主键范围的sql语句.以前的做法是在sp中再根据这个sql语句拼出来返回最终结果的更大的语句.发现这样子的语句往往效率很低,而且数据库的改动(例如列名)也往往无法在包编译时被检查出来.

解决的思路是先把这个主键范围的值查询出来,再用这个查询的结果和其他的表作链接,这样最终的sql就不再是字符串格式了.因为主键范围相对比较小,效率也会提高很多.

于是求助于Oracle的临时表,这看起来是存放主键查询结果的理想的地方. 首先想到的是事务型的,但是发现在前台的.Net程序执行了存储过程之后,默认执行了commit操作,所以返回的结果都是"对象已经不存在".还没有搞懂游标的返回机制,但这看起来有些釜底抽薪的意思.

因此转而投奔会话型的,查询的结果在事务完成后仍会予以保留,只要连接没有断调 -- 这在我们这个C/S架构的程序中是可以满足的. 一个新的问题又出来的,就是如何保证两次执行不会发生影响. 现在的做法是简单的在每次执行前truncate掉临时表,这样,每一次执行时候,存储过程所看到的都是一张空表. 至此,大部分的问题便以这种颇为怪异的方式解决了.

但是问题仍然是有的.就是并发的问题.因为是C/S架构,当前每一个连接是局限在一个客户端内,而在同一个客户端产生这类并发的机会相对较小(不是没有).刚刚想到一个可能的思路是每一次查询完毕后,先去到数据,然后立即关闭连接,这样临时表中的数据就会被自动截断.明天去试一试.

一段小插曲,一个哥们在网上搜oracle临时表相关的材料,发给我一段类似下面的代码:

declare @table1 Table (cust_id int not null)
insert into @table1 select cust_id from customer

总觉得看着眼熟,但是在oracle中怎么编译都不通过.一直到我把目光盯住了那个@ ..... 我终于明白了,这个是SqlServer中的代码,ft啊,半年不用就退化到这个地步了


原文转自:http://www.ltesting.net