使用表变量/全局临时表来编码此PL / SQL函数

时间:2011-01-31 23:12:15

标签: oracle variables plsql

我使用的是Oracle 11g,我有很多存储过程代码使用相同的SELECT语句(但是复杂的语句),只是where子句中的不同输入:

select ... where ancestor = X

现在将SELECT语句复制/粘贴到数百个这样的语句中,我需要重构,因此它们使用相同的SELECT语句构造。因为所有这些存储过程已经存在,所以重构必须与当前代码很好地协同工作,如下所示:

create or replace procedure Foo
begin
  select quantity, amount from TBRawData, (select ... where ancestor = X) temp, where TBRAWData.StoreID = temp.StoreID;
end;

简而言之,我需要一种标准化SELECT的PL / SQL方法,但是ref游标,数组类型,集合等都不会起作用,因为它们不像表一样(因此不能内部连接到TBRAWData )。全局临时表会在这里工作还是其他什么?

请帮忙!

2 个答案:

答案 0 :(得分:4)

查看是一个很好的答案(感谢 Gary ),但还有另一种可能性。

您可以在数据库模式中创建对象类型,并引用它的表类型:

create or replace type TFooDataRecord as object (
   quantity number,
   amount number
);

create or replace type TFooDataList as table of TFooDataRecord;

然后,声明函数返回所需的结果:

create or replace function GetFoo(pAncestor in number) return TFooDataList
as 
  vResult TFooDataList;
begin

  select TFooDataRecord(quantity, amount)
  bulk collect into vResult
  from TBRawData, (select ... where ancestor = pAncestor) temp, 
  where TBRAWData.StoreID = temp.StoreID;

  return vResult;

end;

然后,您可以在select语句和连接中使用函数:

select foo_func.amount 
from 
  table( GetFoo(123) ) foo_func,
  some_another_table   foo2
where 
  foo_func.quantity < foo2.quantity 

当然,您可以将功能放入包中。 但不是对象和表类型声明。

如果函数返回的行数不是太大(取决于服务器硬件,但通常不超过1000-2000条记录),此解决方案适用。

它比使用视图更好,因为Oracle将为参数化查询维护单个编译和缓存计划,并且不为每个查询重建它,就像带有视图的解决方案一样。

答案 1 :(得分:2)

以什么方式复杂化?

如果您在谈论SELECTed表达式,请查看virtual columns 视图可以是封装查询复杂性的好方法。我通常会使用连接谓词将所选列放在那里,并将过滤谓词留给调用查询。

例如,如果我有

SELECT a.col_a1, a.col_a2, b.col_b3
FROM table_a a join table_b b on a.col_a1 = b.col_b1
WHERE b.col_b4 = 'Blue'

我会

CREATE VIEW v_1 AS
SELECT a.col_a1, a.col_a2, b.col_b3, b.col_b4
FROM table_a a join table_b b on a.col_a1 = b.col_b1

SELECT v_1.col_a1, v_1.col_a2, v_1.col_b3
FROM v_1
WHERE v_1.col_b4 = 'Blue'

有时候,视图会使优化器变得复杂和混乱(我在组合视图和数据库链接时遇到了非常糟糕的经历)。