Книга: Firebird РУКОВОДСТВО РАЗРАБОТЧИКА БАЗ ДАННЫХ
Процедура с промежуточными итогами
Процедура с промежуточными итогами
В этой процедуре мы обрабатываем записи таблицы SALES базы данных EMPLOYEE. Мы получим два итога: один для каждого вида продаж, а другой - для всех продаж. В качестве входа мы просто используем начальную и конечную даты для группы интересующих нас продаж.
SET TERM ^;
CREATE PROCEDURE LOG_SALES (
.START_DATE DATE,
END_DATE DATE)
RETURNS (REP_NAME VARCHAR (37) ,
CUST VARCHAR(25),
ORDDATE TIMESTAMP,
ITEMTYP VARCHAR(12),
ORDTOTAL NUMERIC(9,2),
REPTOTAL NUMERIC(9,2),
RUNNINGTOTAL NUMERIC(9, 2))
AS
DECLARE VARIABLE CUSTNO INTEGER;
DECLARE VARIABLE REP SMALLINT;
DECLARE VARIABLE LASTREP SMALLINT DEFAULT -99;
DECLARE VARIABLE LASTCUSTNO INTEGER DEFAULT -99;
BEGIN
RUNNINGTOTAL = 0.00;
FOR SELECT
CUST_NO,
SALES_REP,
ORDER_DATE,
TOTAL_VALUE,
ITEM_TYPE
FROM SALES
WHERE ORDER_DATE BETWEEN : START_DATE AND :END_DATE + 1
ORDER BY 2, 3
INTO :CUSTNO, : REP, : ORDDATE, :ORDTOTAL, : ITEMTYP
Заметьте, что мы используем упорядоченный набор. Если вы получаете виртуальную таблицу из хранимой процедуры выбора и вам нужен упорядоченный набор, полезно сделать набор упорядоченным внутри кода процедуры. Оптимизатор может улучшить здесь производительность, если существуют полезные индексы, в то время как упорядочение, применяемое к выходному набору, не может использовать индексов по своей природе.
Внутри цикла мы начинаем использовать данные для нашей строки и для получения итогов. Мы используем немного магии, чтобы избежать повторений имени - это выглядит изящнее при отображении только для чтения - хотя вы не должны делать этого, если вашему приложению нужно получить строки в произвольном порядке и оно использует этот столбец в качестве ключа поиска! Мы управляем именем покупателя похожим образом для исключения ненужного поиска, когда тот же покупатель появляется в последовательных записях.
DO
BEGIN
IF(REP = LASTREP) THEN
BEGIN
REPTOTAL = REPTOTAL + ORDTOTAL;
REP_NAME = "" ;
END
ELSE
BEGIN
REPTOTAL = ORDTOTAL;
LASTREP = REP;
SELECT FULL_NAME FROM EMPLOYEE
WHERE EMP_NO = :REP
INTO :REP_NAME;
END
IF (CUSTNO <> LASTCUSTNO) THEN
BEGIN
SELECT CUSTOMER FROM CUSTOMER
WHERE CUST_NO = :CUSTNO
INTO :COST;
LASTCUSTNO = CUSTNO;
END
RUNNINGTOTAL = RUNNINGTOTAL + ORDTOTAL;
SUSPEND;
Теперь наша строка готова и отправляется в кэш строк вместе с двумя обновленными итогами.
END
END^
SET TERM ;^
Вызов процедуры
Наши входные аргументы имеют тип данных DATE- начальная дата и конечная дата. Процедура отыскивает тип данных TIMESTAMP для выборки строк для курсора. Она добавляет один день к конечной дате, чтобы гарантировать получение каждой строки вплоть до конца этого дня. Это упрощает дела: когда мы вызываем процедуру, нам нужно только предоставить первую и последнюю даты при отсутствии беспокойства по поводу записей с датой более поздней, чем полночь последнего дня.
Следующий вызов возвращает целую таблицу:
SELECT * FROM LOG_SALES ('16.05.1970', CURRENT_3ATE);
Мы можем обратиться к процедуре с использованием параметров:
SELECT * FROM LOG_SALES (?, ?);
- 4.3. Процедура инсталляции
- Работа с массивами в хранимых процедурах
- Процедура установки Parallels Workstation
- Глава 5 ПРОЕКТНАЯ ПРОЦЕДУРА РАЗРАБОТКИ ФУНКЦИОНАЛЬНЫХ ОПИСАНИЙ
- 5.8.2. Взаимосогласительная процедура
- Процедура графологического анализа
- Правила, применимые к процедурам создания
- 5.3.4. Процедура утверждения QA
- Простая процедура с вложенными операторами SELECT
- Процедура установки VMware Workstation
- 2.5. ПРОЕКТНАЯ ПРОЦЕДУРА ПОСТАНОВКИ ЗАДАЧИ РАЗРАБОТКИ ПРОГРАММЫ
- 8.8. ПРОЕКТНАЯ ПРОЦЕДУРА ОБЪЕКТНО-ОРИЕНТИРОВАННОГО ПРОЕКТИРОВАНИЯ ПО Б. СТРАУСТРУПУ