Суспенды и таблицы

Jan 22, 2013 16:47

Больше всего мне в файербёрде нравились селективные процедуры. И ещё анонимные курсоры. Ну, наверное они так называются... По-порядку.
Многие люди, знакомые с PL/SQL, но незнакомые с файербёрдом округляют глаза на словосочетани селективная процедура. на самом деле всё просто. Селективная процедура может возвращать набор данных. Ну, почти как табличка. За исключением того, что в табличку нельзя передать входной параметр, а в процедуру можно. А потом с селективной процедурой можно поступить примерно так:

select id
, name
from select_foreign_users('PENTAGON_DATABASE')

В селективной процедуре дополнительно к входным параметрам объявляются выходные. А также вот тут вот самая прикольная штука, всякий раз, как нужно вернуть запись из процедуры внутри у ней нужно написать suspend; . Суспенд делает усилие и выталкивает наружу очередную порцию данных. Вот что было в переменных, объявленных как выходные, вот то и вытолкнет. Ну вот примерно так:

create or alter procedure select_foreign_users (
dtbase varchar(100))
returns (
id integer,
name varchar(100),
superability varchar(200)
)
as
begin
for select id, login, permisson
from user_databases
where database_name=:dtbase
into :id, :name, :superability
do begin
suspend;
end;

if (dtbase='PENTAGON_DATABASE') then begin
id=0;
name='PUTIN';
superability='UNDERCOVER_AGENT';

suspend;    end;
end
Первый параметр dtbase, как многие уже догадались - входной. Те, что в блоке returns выходные.  О, да-да, не останавливайся, Капитан Очевидность!  Далее - собсно тушка процедуры.
В начале прикольный цикл for, фишечка FB. Ну как бы анонимный курсор. Цикл пробегает по выдаче запроса и на каждой итерации заносит в переменные, которые перечислены в into, очередные значения. Как многие догадываются, количество локальных переменных в into должно совпадать с количеством столбцов запроса, а типы должны быть совместимыми. Внутри цикла переменные суспендятся - передаются на выход процедуры.
Со второй частью тоже всё ясно - на выход процедуры будут подан ещё один ряд, если условие выполнится.
В общем, очень сильное колдунство, этот ваш suspend. Очень мне он нравится.

А что же Oracle? Оракл не умеет селективные процедуры. Вот такой вот недомерок по сравнению с ФБ. Мог бы за 30-то с лишним лет и повзрослеть.
Но в Оракле, конечно же, миллион всяких других полезных вещей, которые, собсно, делают гораздо больше, чем селективные процедуры. Ну вот хоть пользовательские типы данных. И если ФБ в этом вопросе ограничивается системой доменов - просто пользовательское имя для стандартного типа, то Оракл углубляется.
Можно объявить запись. Ну, как в Си - record:

type t_person_rec is record (
id number
, name varchar2(100)
, superability varchar2(200)
);

Потом взять да сделать тип "таблица" из этих записей:

type t_person_tab is table of t_person_rec index by binary_integer;

И вот переменные типа t_person_tab можно хоть передавать, хоть возвращать... Чего угодно можно с ними делать. Плюсов куча - можно внутрь процедуры передать таблицу (а не извращаться через GTD, как в файербёрде), можно вернуть несколько разных таблиц из процедуры. Минус только один - suspend некуда прилепить :)

Обращаться к таким переменным можно совершенно естественным путём - через индексы и точки. Ну, типа вот так:

person_table_var(1).id := 0;
person_table_var(1).name := 'PUTIN';
person_table_var(1).superability := 'UNDERCOVER_AGENT';

Да, тут присваивание, как в Паскале. В файербёрде - как в Си, а в Оракле, как в Паскале... До сих пор иногда это двоеточие забываю...

работа, sql, firebird, oracle

Previous post Next post
Up