PL / SQL嵌入到表中可能不存在

时间:2010-03-17 14:51:39

标签: sql oracle plsql

我更喜欢在pl / sql块中使用这种'嵌入'样式插入(与执行立即样式动态sql相反 - 你必须在其中划定引号等)。

-- a contrived example
PROCEDURE CreateReport( customer IN VARCHAR2, reportdate IN DATE )
BEGIN

   -- drop table, create table with explicit column list
   CreateReportTableForCustomer;

   INSERT INTO TEMP_TABLE 
   VALUES ( customer, reportdate );
END;
/

这里的问题是oracle检查'temp_table'是否存在以及它是否具有正确的colunms数并且如果它不存在则抛出编译错误。

所以我想知道是否有任何方式围绕那个?!本质上我想使用占位符表示表名来欺骗oracle而不检查表是否存在。

修改

我应该提到用户可以执行任何“报告”(如上所述)。一种机制,它将执行任意查询但始终写入temp_table(在用户的模式中)。因此,每次运行报告proc时,它都会删除temp_table并使用不同的列列表重新创建它。

3 个答案:

答案 0 :(得分:5)

您可以使用动态SQL语句插入可能存在的temp_table,然后捕获并处理表不存在时发生的异常。

示例:

execute immediate 'INSERT INTO '||TEMP_TABLE_NAME||'  VALUES ( :customer, :reportdate )' using customer, reportdate;

请注意,在动态SQL语句中使表名有所不同,所以如果确保表名保持不变,那就最好了。

答案 1 :(得分:5)

也许您应该使用global temporary table(GTT)。这些是永久表结构,用于保存Oracle会话的临时数据。许多不同的会话可以将数据插入到同一GTT中,并且每个会话只能看到自己的数据。根据GTT的定义,数据会在COMMIT或会话结束时自动删除。

您可以像这样创建GTT(仅限一次):

create globabal temporary table my_gtt
(customer number, report_date date) 
on commit delete/preserve* rows;

*删除适用

然后你的程序可以像任何其他表一样使用它 - 唯一的区别是你的会话总是空着。

答案 2 :(得分:1)

使用GTT比暂时删除/重新创建表更为可取 - 如果您的应用程序需要为每个报表使用不同的结构,我强烈建议您计算出每个报表所需的所有不同结构,并根据需要创建单独的GTT。每个,而不是在运行时创建普通表。

那就是说,如果这是不可行的(并且我已经看到了不好的例子,例如在支持用户广泛的临时请求的系统中),你将不得不使用EXECUTE IMMEDIATE方法。