Опубликован: 25.09.2009 | Уровень: специалист | Доступ: свободно
Лекция 5:

Блоки на основе FROM CLAUSE

< Лекция 4 || Лекция 5 || Лекция 6 >
Аннотация: В этой лекции слушатель научится создавать новый источник данных для блока, а также ознакомится с конвейерными (pipelined) функциями, которые будут рассматриваться как один из возможных источников.

Ранее мы рассматривали создание блоков на основе таблиц, представлений, синонимов. В принципе это достаточный набор объектов, так как для реализации иерархических запросов JOIN (cross, natural, inner, outer и т.д.) или запросов с группировкой вам достаточно будет создать блок на основе представления. А что делать, если у разработчика нет привилегии на создание представления? Или необходимо сделать блок на основе функции? Ответом на эти вопросы как раз и является свойство блока Query Data Source Type — FROM CLAUSE.

Свойства для работы с FROM CLAUSE

Для начала определимся, что такое FROM CLAUSE.

FROM CLAUSE используется в качестве источника данных ( Data Source ) для блока, позволяющего использовать вложенные операторы SELECT в конструкции FROM. Значение, возвращаемое FROM CLAUSE, – это подмножество записей первоначального (original query) запроса. В основном FROM CLAUSE используется для реализации соединения (joins), связывания (lookups), вычисления и агрегации без создания представления на сервере, поэтому FROM CLAUSE может также применяться как прототип представления и повысить производительность вашего приложения.

Примечание: блоки, основанные на FROM CLAUSE , – это блоки типа Query Only, то есть блоки, позволяющие выполнять только запросы.

Перейдем к практической части, в которой мы выполним два несложных упражнения:

  • создание блока на основе запроса с группировкой;
  • создание блока на основе Pipelined Function.

Блок на основе запроса с группировкой

Для начала рассмотрим пример с созданием блока на основе запроса с группировкой.

  1. Создайте таблицу NUMB:
    create table numb(A number);
  2. Заполните таблицу значениями:
    begin
     for i in 1..10 loop
      insert into NUMB values(i); 
     end loop; 
    end;
  3. Измените таблицу так, чтобы появились дубли:
    update NUMB set A=4 where A=7; 
    update NUMB set A=5 where A=6;
  4. Проверьте содержимое таблицы:
    select * from NUMB;
    A --------
    1
    2
    3
    4
    5
    5
    4
    8
    9 10
    10 rows selected.
  5. Выполните запрос с группировкой, который будет источником для блока:
    select A from numb group by a;
    A --------
    1
    2
    3
    4
    5
    8
    9 10
    8 rows selected.

Теперь, когда все готово для выполнения примера, создадим новую форму FORM_1. Создайте блок данных вручную. Выберите блок в объектном навигаторе и вызовите палитру свойств. Установите свойства блока следующим образом:

  • Query Data Source Type – определяет тип источника данных для блока. Установите этот параметр на FROM CLAUSE.
  • Query Data Source Name – текст вложенного запроса (nested query). В этом свойстве введите текст запроса:
    select A from numb group by a
  • Свойство Database item установите равным " Yes ".
  • Name – значение этого свойства установите равным " Num ".

Создайте одну кнопку и один текстовый элемент с параметрами:

  • Свойство Database item установите равным " Yes " (иначе получите ошибку unable to perform query).
  • Column name – это свойство установите равным A (имя должно совпадать с именем столбца в запросе, иначе также получите ошибку unable to perform query).

Создайте триггер WHEN-BUTTON-PRESSED:

go_block ('NUMB'); 
execute_query;

Мы рассмотрели очень простой, но показательный пример, который поможет вам понять назначение FROM CLAUSE и способы его использования в реальных и более сложных задачах.

Создание блока на основе Pipelined Function

Данный пример практически ничем не будет отличаться от предыдущего, за тем исключением, что в качестве источника данных мы возьмем функцию, возвращающую массив данных. В примере мы рассмотрим функцию с параметрами, чтобы вы могли ясно представить, какие возможности может вам дать использование данного типа источника. Выполнение примера можно разбить на две части:

  • написание функции;
  • создание формы.

Приступим к первой части.

Создадим простую Pipelined -функцию, возвращающую набор данных в виде последовательности чисел:

create type "virtual_table_type" as table of number;
create or replace function "pipe_table" (p_num_rows in number, l_order varchar2)
return "virtual_table_type" pipelined
is type t_data is ref cursor; 
c_data t_data; 
cursor c1 is select * from numb; 
c2 c1%rowtype; 
begin
 open c_data for 'select * from numb 
  order by'||l_order; 
 for i in 1 .. p_num_rows loop
  fetch c_data into c2; pipe row(c2.a); 
 end loop; 
 return; 
end "pipe_table";
select * from table("pipe_table"(5,' a desc'));
COLUMN_VALUE
---------
10
9
8
5
5

Функция готова, теперь можно перейти к следующему шагу. Но прежде чем начать, давайте рассмотрим еще один небольшой пример, чтобы не ограничиваться отображением данных из Pipelined -функции и показать, как можно другому блоку назначить новый источник данных.

  1. К существующей форме добавьте еще один базовый блок на таблицу Numb с одним текстовым полем А. В блоке NUM измените свойство Query Data Source Name на select * from table(vt(5,' a desc')).
  2. Добавьте в триггер WHEN-BUTTON-PRESSED следующие строки:
    go_block('NUM');
    execute_query;
    go_block('NUMB');
    set_block_property('NUMB', query_data_source_type,
    get_block_property( 'NUM', query_data_source_type));
    set_block_property('NUMB', query_data_source_name,
    get_block_property( 'NUM', query_data_source_name));
    execute_query;

Запустите форму на выполнение. В результате у вас в обоих элементах должны отобразиться одинаковые данные. Этот простой пример должен помочь вам закрепить ранее выполненное упражнение, и вы сможете применить данную функциональность в своих приложениях. Приведем простой пример, когда, имея форму с одним блоком данных, вы хотите просматривать набор не только отсортированных данных или ограниченных условием WHERE Clause, но и сгруппированных. Вам не придется создавать много представлений на сервере – достаточно создать несколько блоков с различными источниками данных и назначать их основному при нажатии кнопки.

< Лекция 4 || Лекция 5 || Лекция 6 >
Константин Лукин
Константин Лукин

ошибка: FRM47337  Tree node label can not be null

при выполнении скрипта

DECLARE
 Itree ITEM;
 top_node Ftree.Node;
 new_node Ftree.Node;
 i_value VARCHAR2(30);
BEGIN
 Itree := Find_Item('tree_block.tree_item ');
 new_node := Ftree.Add_Tree_Node(Itree, Ftree.ROOT_NODE,
   Ftree.PARENT_OFFSET, Ftree.LAST_CHILD,
   Ftree.EXPANDED_NODE, i_value, NULL, i_value);
END;

Юлия Малыгина
Юлия Малыгина
приведена функция скрытия URL отчета и ее применение, но применения так и нет
Жанбек Сарсенов
Жанбек Сарсенов
Россия, Москва, Московский Государственный Университет имени Ломоносова М.В., 2002