Posts Tagged ‘oracle’

Как задать и использовать константу в виде коллекции на Pl/SQL.

Среда, Июль 2nd, 2014

Иногда в реальных задачах необходимо в константах хранить какую-либо коллекцию. На языке pl/sql просто создать коллекцию и перечислить через запятую данные, которые она будет содержать, нельзя. Такое возможно только с массивами, у которых строго задан размер и тип элементов. Если же возникла необходимость сделать предопределенную коллекцию-константу, то в этом случае её не получится проинициализировать простым перечислением данных. Чтобы проинициализировать коллекцию–константу, необходимо задать функцию, которая вернет заполненную коллекцию для присвоения её в указанную переменную. Выглядеть это будет примерно так, как показано ниже.

Например, мы хотим создать коллекцию действий пользователя, индекс элемента которой будет представлять собой символьный код операции, а значение — название операции, которое увидит пользователь. Зададим возможные действия константами, так как в дальнейшем в программе они обрабатываются.
[code]
subtype typeActionName is varchar2(50); — Тип: Код действия
type typeActionCol is table of typeActionName — Тип: Список действий
index by varchar2(200);

cOperSetDefault constant typeOperName:= ‘SetDefault’;
cOperUndoDefault constant typeOperName:= ‘UndoSetDefault’;
cOperChangeParam constant typeOperName:= ‘ChangeParam’;
cOperClose constant typeOperName:= ‘CLOSE’;
cOperOpen constant typeOperName:= ‘UNCLOSE’;
cOperDelete constant typeOperName:= ‘Delete’;
cOperAddItem constant typeOperName:= ‘AddItem’;

function setActionCollection return typeOperCol; —функция задания массива кода операции и имени операции

ActionCollection constant typeOperCol:= setActionCollection; —список действий пользователя

function setActionCollection return typeActionCol
is
pOperCol typeActionCol;
begin
pOperCol(cActionSetDefault) := ‘Установить параметры по умолчанию’;
pOperCol(cActionUndoDefault) := ‘Вернуть параметры, которые были до сброса’;
pOperCol(cActionCloseAgree) := ‘Закрыть соглашение’;
pOperCol(cActionOpenAgree) := ‘Открыть соглашение’;
pOperCol(cActionChangeParam) := ‘Изменить значение параметров;
pOperCol(cActionDelete) := ‘Удалить элемент’;
pOperCol(cActionAddItem) := ‘Добавить элемент’;
return pOperCol;
end;
[/code]

Таким образом можно задать коллекцию, содержащую данные любого составного типа. В зависимости от типа будет меняться только функция его заполнения (либо усложнятmся, либо упрощаться). После того, как мы объявили свою константу, возникает вопрос: как выполнить какие-либо операции при помощи данных, которые мы проинициализировали? Если рассматривать коллекцию, которую я привела выше, то для обхода её потребуется массив индексов.
[code]
type typeColkeys is varray(7) of typeOperName;

—массив для индексации действий
Collectionkeys typeColkeys := typeColkeys (cActionSetDefault, cActionUndoDefault, cActionCloseAgree, cActionOpenAgree, cActionChangeParam, cActionDelete, cActionAddItem);
[/code]

А после этого можно будет пройти по коллекции циклом и выполнить необходимые вам операции.

[code]
FOR i IN 1..ActionCollection.count loop
—выполняем необходимые операции
—Collectionkeys(i) – это будет код действия пользователя
—ActionCollection(Collectionkeys(i)) –это будет заголовок действия
end loop;
[/code]

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

Конструкция select for update

Четверг, Апрель 10th, 2014

Ни для кого не секрет, что в различных СУБД блокирование реализовано по разному. Есть несколько основных принципов блокирования в СУБД Oracle, незнание которых может привести к возникновению ошибок в приложениях.

  • Oracle блокирует данные на уровне строк и только при изменении. Эскалация блокировок до уровня блока или таблицы никогда не выполняется.
  • Oracle никогда не блокирует данные с целью считывания. При обычном считывание блокировки на строки не устанавливаются.
  • Сеанс, записывающий данные не блокирует сеанс, читающий данные.
  • Сеанс записи данных блокируется, только если сеанс записи уже заблокировал строку, которую предполагается изменять. Сеанс считывания данных никогда не блокирует сеанс записи.

(далее…)

Oracle APEX: Итоги в Interactive report на каждой странице [RU]

Четверг, Ноябрь 14th, 2013

Одним из самых мощных инструментов визуализации данных в Oracle APEX является Interactive Report. Он предоставляет богатые возможности поиска, фильтрации, сортировки и вычисления итогов. Но есть ряд задач, часто возникающих в разработке бизнес-приложений, которые вызывают сложности. В нескольких постах я хочу предложить простой выход из положения.

Первым рассмотрим тривиальный вопрос — вывод итогов по всем данным на каждой странице отчета. При использовании встроенных итогов в IR, итоги выводятся на самой последней странице, если страниц несколько. В реальных приложениях очень часто итоги как раз и будут целью фильтрации и отображения данных — пользователю нужно сначала увидеть общую сумму, а потом уже, если она устраивает, смотреть детализацию. Если после применения фильтра пользователю приходится «отмотать» сначала 10-20 страничек, либо грузить ооочень длинную таблицу — пользователь звереет.

Оптимальным выходом является отображение итогов на каждой странице, но IR не предоставляет такой возможности. Значит, сделаем это сами.

In english, please…

(далее…)

Как создать индекс в Oracle, если таблица занята.

Среда, Октябрь 2nd, 2013

Иногда бывают такие ситуации, когда что-то случилось с индексами на важной таблице. Если работа с БД непрерывная и эта таблица очень часто занята, восстановить индексы достаточно проблематично, так как ресурс постоянно занят. Конечно можно поймать такой момент когда СУБД даст возможность создать index. Однако если эта проблема всплыла только после запуска длительной и важной операции, которая не требует отлагательств. Так как объект занят вам придется писать код создания индекса и сидеть давить, ловя момент когда пройдет commit и объект разблокируется. Не очень радужные перспективы. По-этому умные люди в Oracle подумали об этом. В Oracle Enterprise Edition есть возможно запустить создание индекса в режиме ожидания. К сожалению уже в версии Standard Edition данная возможность отсутствует. Что бы запустить создание индекса, когда ресурс занят необходимо дописать в конце ONLINE.

CREATE INDEX index_name ON table_name (column_name, column_name, column_name, column_name) ONLINE;

Операция запуститься и будет ждать момента, когда ресурс освободится. Как только пройдет commit запустится создание индекса. Имейте в виду, что время, необходимое для завершения построения онлайн индекса пропорциональный размеру таблицы и числу одновременно выполняющихся DML отчетности. Поэтому, лучше всего, начинать оперативное построение индекса при низкой DML активности.

Очень полезная feature. Если у вас версия Enterprise Edition советую пользоваться, так как она нужна не только в ситуации, которую описала я. Почитать документацию об этом можно здесь.