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

发布于 2024-10-15 15:44:36 字数 558 浏览 1 评论 0原文

我使用的是 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 方法,但需要一个引用游标、数组类型、集合和这样将不起作用,因为它们不被视为表(因此不能内部连接到 TBRAWData)。全局临时表可以在这里工作,还是其他什么?

请帮忙!

I am using Oracle 11g, and I have a lot of stored procedure code that use the same SELECT statement (but a complex one), just a different input in a where clause:

select ... where ancestor = X

That SELECT statement right now is copied / pasted on hundreds of these, and I need to refactor so they use the same SELECT statement construction. Because all these stored procs already exist, the refactoring must work nicely with the current code, which looks like this:

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

In a nutshell, I need a PL/SQL means of standardizing a SELECT, but a ref cursor, array types, collections, and such will not work because they are not treated like a table (thus cannot be inner joined to TBRAWData). Would a global temporary table work here, or something else?

Please help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

难以启齿的温柔 2024-10-22 15:44:36

View 是一个很好的答案(感谢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 foo_func.amount 
from 
  table( GetFoo(123) ) foo_func,
  some_another_table   foo2
where 
  foo_func.quantity < foo2.quantity 

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

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

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

View is good answer(thanks to Gary), but there is another possibility.

You can create object type in database schema and table type referenced it:

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

create or replace type TFooDataList as table of TFooDataRecord;

then, declare function returning required results:

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;

then, you can use function in select statements and joins:

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

Of course, you can place function into the package.
But not object and table type declarations.

This solution applicable if number of rows returned by function is not too big (depends on server hardware, but generally not more than 1000-2000 records).

It better than use of view because Oracle would maintain single compiled and cached plan for parametrized query and don't rebuild it for each query as in case of solution with view.

花开浅夏 2024-10-22 15:44:36

复杂到什么程度呢?

如果您正在讨论 SELECTed 表达式,请查看虚拟列
视图是封装查询复杂性的好方法。我通常会将选定的列与连接谓词一起放入其中,并将过滤谓词留给调用查询。

例如,如果我有的

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'

有时视图会使优化器变得复杂和混乱(并且我在组合视图和数据库链接方面有过非常糟糕的经历)。

Complicated in what way ?

If you are talking about SELECTed expressions, look at virtual columns
Views can be a good way of encapsulating query complexity. I would generally put the selected columns in there with the join predicates and leave filter predicates to the calling query.

For example if I have

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'

I would

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

and

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

Sometimes views can complicated and confuse the optimizer (and I've had very bad experiences combining views and database links).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文