Firebird РУКОВОДСТВО РАЗРАБОТЧИКА БАЗ ДАННЫХ
Шрифт:
RUNNINGTOTAL = RUNNINGTOTAL + ORDTOTAL;
SUSPEND;
Теперь наша строка готова и отправляется в кэш строк вместе с двумя обновленными итогами.
END
END^
SET TERM ;^
Наши входные аргументы имеют тип данных DATE- начальная дата и конечная дата. Процедура отыскивает тип данных TIMESTAMP для выборки строк для курсора. Она добавляет один день к конечной дате, чтобы гарантировать получение каждой строки вплоть до конца этого дня. Это упрощает дела: когда мы вызываем процедуру, нам нужно только предоставить первую и последнюю
Следующий вызов возвращает целую таблицу:
SELECT * FROM LOG_SALES ('16.05.1970', CURRENT_3ATE);
Мы можем обратиться к процедуре с использованием параметров:
SELECT * FROM LOG_SALES (?, ?);
Просмотр массива в хранимой процедуре
Если в таблице есть столбцы, определенные как массивы, вы не сможете просмотреть данные в таком столбце в простом операторе SELECT, потому что в таблице хранится только идентификатор массива. Хранимая процедура может быть использована для отображения значений массива, если размерность и тип данных столбца массива заранее известны.
Таблица JOB В примере базы данных имеет столбец LANGUAGE REQ, содержащий требуемые языки. Столбец определен как массив из пяти элементов VARCHAR(15).
Следующий пример использует хранимую процедуру для просмотра содержимого этого столбца. Процедура использует цикл FOR ... SELECT для поиска каждой строки из таблицы JOB, где столбец LANGUAGE_REQ не является пустым. Затем цикл WHILE отыскивает каждый элемент массива и возвращает значение вызвавшему приложению.
SET TERM ^;
CREATE PROCEDURE VIEW_LANGS
RETURNS (
code VARCHAR(5) ,
grade SMALLINT,
cty VARCHAR(15),
lang VARCHAR(15))
AS
DECLARE VARIABLE i INTEGER;
BEGIN
FOR SELECT
JOB_CODE,
JOB_GRADE,
JOB_COUNTRY
FROM JOB
WHERE LANGUAGE_REQ IS NOT NULL
DO
BEGIN
i = 1;
WHILE (i <= 5) DO
BEGIN
SELECT LANGUAGE_REQ[:i] FROM JOB
WHERE ((JOB_CODE = :code)
AND (JOB_GRADE = :grade)
AND (JOB_COUNTRY = :cty))
INTO :lang;
i =i + 1;
SUSPEND;
END
END
END ^
SET TERM ; ^
Ее вызов:
SELECT * FROM VIEW_LANGS;
CODE GRADE CTY LANG
Eng 3 Japan Japanese
Eng 3 Japan Mandarin
Eng 3 Japan English
Eng 3 Japan
Eng 3 Japan
Eng 4 England English
Eng 4 England German
Eng 4 England French
. . .
Процедура может быть модифицирована таким образом, что будет получать входные аргументы и возвращать другую комбинацию данных в качестве выхода.
Тестирование процедур
Разработчикам не нужно напоминать о необходимости строгого тестирования модулей PSQL, прежде чем передавать их в работу, где они в один скверный день могут принести большой вред. Синтаксический анализатор предупредит вас об ошибках кодирования PSQL, однако как программы ваши модули не защищены от логических ошибок, как и любой код приложения, который вы пишете.
Например, наша процедура LOG SALES прекрасно работает, пока каждая запись продаж имеет непустое значение SALES REP. При этом данный столбец допускает пустое значение. Процедура генерирует результирующий набор, в котором каждая выходная строка зависит от значений в предшествующих строках. Если мы не учтем возможные
эффекты появления значения NULL В таком ключе, наша процедура выдаст неверный результат. Позже в этой главе в разд. "Изменение хранимых процедур" мы добавим меры предосторожности при работе, когда могут появиться некоторые проблемы.Процедуры для совместного использования
Хотя возможно написание процедуры выбора, которая будет выполнять операции по изменению данных в процессе конструирования выходного набора, этого делать не рекомендуется. Хранимая процедура выбора разрабатывается для вывода набора данных клиенту в контексте вызвавшей ее транзакции. Пока клиентское приложение не завершит использование этого выходного набора, транзакция остается неподтвержденной. Если операции DML включены в код, который генерирует выходной набор, эти запросы DML остаются неподтвержденными, пока транзакция не будет завершена клиентом.
В частности, данные могут потенциально сохраняться в несогласованном виде, если значения выхода хранимой процедуры выступают в качестве параметров для операций в других транзакциях.
Изменение хранимых процедур
Firebird 1.0.x предоставляет два способа изменения хранимых процедур с использованием операторов DDL, a Firebird 1.5 добавляет еще и третий. Это:
* оператор ALTER PROCEDURE, который изменяет определение существующей хранимой процедуры, сохраняя ее взаимозависимости с другими объектами;
* оператор RECREATE PROCEDURE, который выполняется, даже если указанная процедура не существует. Если она существует, то эта версия удаляется, а затем заново создается. Существующие зависимости не сохраняются;
* оператор CREATE OR ALTER PROCEDURE (доступен начиная с версии 1.5) предоставляет лучший вариант. Если процедура существует, применяются правила ALTER, зависимости сохраняются. Если не существует, то будет работать точно так же, как и CREATE PROCEDURE.
Любая из этих операций вызовет исключение, если любая попытка изменений разрушает зависимости.
Влияние на приложения
Внутренние изменения процедуры прозрачны всем клиентским приложениям, использующим эту процедуру. Вам не нужно пересоздавать приложения, если изменения не коснулись интерфейса между вызывающей программой и процедурой - тип, количество или порядок выходных или выходных аргументов.
Синтаксис изменения процедур
За исключением ключевого слова, которое вы выбрали для изменения хранимой процедуры, синтаксис для всех операторов такой же, как и для CREATE PROCEDURE. Как и в любом другом компилируемом или интерпретируемом модуле, не существует способов непосредственного изменения элементов без полного пересоздания всего модуля. Каждая "переделка", независимо от выбранного ключевого слова для задания операции, имеет дело с созданием новой версии исходного кода и нового двоично- кодированного объекта.
Синтаксис:
{CREATE | ALTER | RECREATE | CREATE OR ALTER} PROCEDURE Имя
[(переменная тип-данных [,переменная тип-данных ...])]
[RETURNS (переменная тип-данных [, переменная тип-данных ...])]
AS
тело-процедуры;
В ALTER PROCEDURE имя процедуры должно быть именем существующей процедуры.
Это мягкий способ изменения кода процедуры, потому что если у нее есть зависимости, на которые логически не влияют изменения, то они не будут влиять на структурную часть.