Использование табличной переменной / глобальной временной таблицы для кодирования этой функции PL / SQL - PullRequest
2 голосов
/ 01 февраля 2011

Я использую Oracle 11g, и у меня есть много кода хранимых процедур, которые используют один и тот же оператор SELECT (но сложный), просто другой ввод в предложении where:

select ... where ancestor = X

ThatОператор SELECT сейчас скопирован / вставлен на сотни из них, и мне нужно провести рефакторинг, чтобы они использовали одну и ту же конструкцию оператора SELECT.Поскольку все эти хранимые процессы уже существуют, рефакторинг должен хорошо работать с текущим кодом, который выглядит следующим образом:

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

В двух словах, мне нужны средства PL / SQL для стандартизации SELECT, ноКурсор ref, типы массивов, коллекции и тому подобное не будут работать, потому что они не обрабатываются как таблица (таким образом, они не могут быть внутренне объединены с TBRAWData).Будет ли здесь работать глобальная временная таблица или что-то еще?

Пожалуйста, помогите!

Ответы [ 2 ]

4 голосов
/ 01 февраля 2011

Просмотр - хороший ответ (спасибо Гари ), но есть и другая возможность.

Вы можете создать тип объекта в схеме базы данных и ссылочный тип таблицы:

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 будет поддерживать один скомпилированный и кэшированный план для параметризованного запроса и не перестраивать его для каждого запроса, как в случае решения с представлением.

2 голосов
/ 01 февраля 2011

Как это сложно?

Если вы говорите о выражениях 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'

Иногда представления могут усложнять и приводить в замешательство оптимизатор (и у меня был очень плохой опыт объединения видов и ссылок на базы данных).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...