ошибка: FRM47337 Tree node label can not be null при выполнении скрипта DECLARE |
Блоки на основе FROM CLAUSE
Ранее мы рассматривали создание блоков на основе таблиц, представлений, синонимов. В принципе это достаточный набор объектов, так как для реализации иерархических запросов 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 может также применяться как прототип представления и повысить производительность вашего приложения.
Перейдем к практической части, в которой мы выполним два несложных упражнения:
Блок на основе запроса с группировкой
Для начала рассмотрим пример с созданием блока на основе запроса с группировкой.
- Создайте таблицу NUMB:
create table numb(A number);
- Заполните таблицу значениями:
begin for i in 1..10 loop insert into NUMB values(i); end loop; end;
- Измените таблицу так, чтобы появились дубли:
update NUMB set A=4 where A=7; update NUMB set A=5 where A=6;
- Проверьте содержимое таблицы:
select * from NUMB; A -------- 1 2 3 4 5 5 4 8 9 10 10 rows selected.
- Выполните запрос с группировкой, который будет источником для блока:
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 -функции и показать, как можно другому блоку назначить новый источник данных.
- К существующей форме добавьте еще один базовый блок на таблицу Numb с одним текстовым полем А. В блоке NUM измените свойство Query Data Source Name на select * from table(vt(5,' a desc')).
- Добавьте в триггер 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, но и сгруппированных. Вам не придется создавать много представлений на сервере – достаточно создать несколько блоков с различными источниками данных и назначать их основному при нажатии кнопки.