我使用的是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 )。全局临时表会在这里工作还是其他什么?
请帮忙!
答案 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'
有时候,视图会使优化器变得复杂和混乱(我在组合视图和数据库链接时遇到了非常糟糕的经历)。