2016-10-18 2 views
2

У меня есть длинная хранимая процедура. Многократно в хранимой proc, подзапрос ниже (в скобках) повторяется.Как использовать подзапрос

and datasetid IN 
    (select datasetid from Reportingdatasetmembers 
    where ReportingDatasetID = param_in_ReportingDataSetID) 

Могу ли я консолидировать этот код, поскольку он повторяется? I.e., в SQL Server, я бы объявил переменную таблицы. Затем вставьте строки в переменную таблицы. Затем запрос к переменной таблицы. По крайней мере, это помогает применять принцип DRY.

Есть ли эквивалентный способ консолидировать это в Oracle? Коллекции таблиц Oracle, похоже, не уменьшают базу кода.

Я считаю, что CTE не может быть и речи, потому что их нельзя использовать повторно?

+0

Является ли 'param_in_ReportingDataSetID' динамическое значение, или оно будет исправлено? –

+0

Это динамический (числовой параметр) – Hoppe

+0

CTEs - отличный способ повторного использования кода, но я не думаю, что они принимают параметры. –

ответ

3

Subquery factoring (ака, CTE в других платформ баз данных) является то, что вам нужно, например:

with dataset as (select datasetid 
       from Reportingdatasetmembers 
       where ReportingDatasetID = param_in_ReportingDataSetID) 
select ... 
from some_table_1 
where ... 
and datasetid in (select datasetid from dataset) 
union all 
select ... 
from some_table_2 
where ... 
and datasetid in (select datasetid from dataset); 
0

создать переменную v_query долго; и затем объявить v_query: = '(выберите datasetid из Reportingdatasetmembers где ReportingDatasetID = 'param_in_ReportingDataSetID')'

и чем v_query вызова Не пробовал, но видел несколько раз, работая

0

В Oracle вы действительно аналогично SQL Server. Объявите переменную типа, являющегося таблицей определенных записей. Что-то вроде:

type my_rec_type is record (v_datasetid number(20)) 
type my_table_type is table of my_rec_type index by pls_integer; 
my_table_var my_table_type; 

... определите параметр для курсора

v_paramReportingDataSetID number(20); 

... в коде вы установите это к конкретному ID

v_paramReportingDataSetID:= 12345; 

.. используйте курсор с инструкцией

open my_cursor for (select datasetid from Reportingdatasetmembers 
    where ReportingDatasetID = :v_paramReportingDataSetID); 

... заполнить табличную переменную из курсора

fetch my_cursor bulk collect into my_table_var; 

... Теперь таблица/массив/данные в my_table_var переменной, пригодный для использования в остальной части кода.

0

@ Правильный способ, но я думаю, вы должны добавить материализовать Подсказка к выбору. Так что это происходит быстрее.

with dataset as (select /*+ materialize */ 
         datasetid 
       from Reportingdatasetmembers 
       where ReportingDatasetID = param_in_ReportingDataSetID) 
select ... 
from some_table_1 
where ... 
and datasetid in (select datasetid from dataset) 
union all 
select ... 
from some_table_2 
where ... 
and datasetid in (select datasetid from dataset); 
+0

Будьте осторожны; materliaze - это недокументированный намек, поэтому поведение может измениться. Я бы не рекомендовал его использовать в производственном коде. Я столкнулся с ошибкой, вызванной этим намеком, поэтому я опасаюсь этого!Кроме того, если подзапрос используется в более чем одном месте в запросе, Oracle, скорее всего, решит материализовать его в любом случае. – Boneist

Смежные вопросы