Главная страница

Р. Кречмер, В. Вейс - Разработка приложений SAP R3 на языке АВАР4. Р. Кречмер, В. Вейс - Разработка приложений SAP R3 на языке АВАР. Разработкаприложений sap r3Рюдигер Кречмерна языкеВольфганг Вейс


Скачать 28.36 Mb.
НазваниеРазработкаприложений sap r3Рюдигер Кречмерна языкеВольфганг Вейс
АнкорР. Кречмер, В. Вейс - Разработка приложений SAP R3 на языке АВАР4.pdf
Дата21.12.2017
Размер28.36 Mb.
Формат файлаpdf
Имя файлаР. Кречмер, В. Вейс - Разработка приложений SAP R3 на языке АВАР.pdf
ТипКнига
#12433
страница11 из 24
1   ...   7   8   9   10   11   12   13   14   ...   24
Глава 12
Использование
внутренних таблиц
Заполнение внутренней таблицы
• Как сортировать содержимое внутренней таблицы
• Чтение одной или нескольких строк
• Изменение содержимого
• Работа с промежуточными суммами

138 Глава 12
В главе 11 внутренние таблицы применялись для построения "моментальных снимков" таблиц базы данных при выполнении программы. Если внутренняя таблица заполнена данными из базы, то разра- ботчик может свободно работать с ними без дополнительных обращений к базе данных. К преимуще- ствам использования внутренних таблиц относится также быстрое выполнение операций, в частности в распределенной среде клиент/сервер. Внутренние таблицы очень удобны в случаях, когда необходимо собрать данные в "контейнер" для дальнейшей обработки в прикладной программе.
В этой главе будут рассмотрены различные методы работы с внутренними таблицами, подробно описаны способы ее заполнения и сортировки по определенным критериям (например, по разным полям или в порядке убывания). Кроме того, будут представлены различные программные приемы чте- ния и изменения содержимого внутренних таблиц, в частности работа с промежуточными суммами.
Изложение материала сопровождается примерами разработки реального приложения.
Что такое внутренняя таблица
Внутренние таблицы определяются (подобно другим объектам данных) с помощью декларации data.
Внутренняя таблица может выполнять роль "моментального снимка" таблицы базы данных и содержать те же строки и столбцы, что и таблица базы данных во время выполнения программы. Такое исполь- зование внутренних таблиц было продемонстрировано в предыдущей главе при описании оператора select. Следующий фрагмент программы показывает, как заполнить внутреннюю таблицу:
data
customers occurs
s e l e c t
i n t o table
Однако во многих случаях функциональное применение внутренних таблиц далеко выходит за гра- ницы простого представления содержимого таблиц базы. Внутренние таблицы могут также содержать дополнительные столбцы с временной информацией, которая используется только в процессе выпол- нения программы и не хранится в базе данных. Так, часто бывает полезно иметь поле, указывающее на возможность удаления текущего элемента, который, как показывают дальнейшие проверки, не при- меняется в других контекстах. Иногда внутренние таблицы могут быть вообще не связаны с какими-либо таблицами базы (например, если при выполнении строятся и выводятся на экран структуры типа дерева или общие связанные списки).
Используя внутренние таблицы, разработчик может не заботиться о распределении динамической памяти — АВАР/4 делает это автоматически. В частности, нет необходимости заранее определять точ- ный максимальный размер внутренней таблицы. Параметр счетчика Occurs Parameter (числовое значе- ние после occurs) позволяет задать предполагаемый максимальный размер, который влияет только на производительность системы и не ограничивает фактического максимального размера внутренней таб- лицы. В принципе внутренняя таблица может иметь бесконечное число строк — оно ограничено лишь размером виртуальной памяти машины, расширение которой сегодня не составляет проблемы. Именно это и является одним из главных преимуществ внутренних таблиц.
Таблицы и строки заголовков
Как отмечалось в главах 4 и 5, если в определении внутренней таблицы применяется дополнение with header line (со строкой заголовка), то АВАР/4 создает собственно таблицу и дополнительный объект данных, называемый строкой заголовка и имеющий ту же самую структуру, что и строка таблицы.
Этот объект используется по умолчанию для хранения текущей строки таблицы. Если таблица не имеет строки заголовка, необходимо выделить отдельную запись для размещения текущей строки, которой оперируют все команды обработки таблицы.
Строка заголовка подобна рабочей области таблицы базы данных. Рабочая область (или альтернативная рабочая область) используется для временного хранения в памяти одного элемента базы (строки) (см. главу 11). Точно так же строка заголовка применяется для хранения одной строки внутренней таблицы. Если таблица базы данных не имеет строки заголовка, отдельная запись для хранения текущего элемента также носит название рабочей области.
Эти два подхода — использование строки заголовка и отдельной записи — обычно идентичны. При пер- вом нет необходимости объявлять дополнительную запись (это делает АВАР/4), и большинство операторов для работы с внутренними таблицами становятся более простыми в смысле понимания (читабельными).
Однако вложенные внутренние таблицы не могут содержать строк заголовка, так как это приводит в неко- торых случаях к неоднозначности выражений. Например, определяется внутренняя таблица:

Использование внутренних таблиц 139
data customers occurs 100
with header l i n e .
При выполнении программы таблица будет выглядеть следующим образом (таблица 12.1):
Таблица 12.1
Содержимое таблицы all_customers
Строка заголовка
00000017
Smith
Содержимое таблицы
00000001
00000002
00000017
87654321
Edwards
Young
Smith
Edison
Small Town
Village
Big City
Fort Myers
+
333-444-2222
717-161-5151
111-111-1111
Во избежание путаницы в понятиях содержимое таблицы (без строки заголовка) будем называть
телом, отличая его тем самым от строки заголовка. Многие ключевые слова АВАР/4 для внутренних таблиц (например, append или loop) учитывают различия между строкой заголовка и телом таблицы,
в то время как другие (в частности, move) — нет. В подобных случаях тело нужно указывать в явном виде с помощью угловых скобок. Более того, у многих операторов форма работы с отдельной записью отличается от формы, работающей со встроенной строкой заголовка. Последний вариант не является обязательным для таблиц со строкой заголовка и необходим в противном случае.
Заполнение внутренней таблицы
В АВАР/4 существует четыре метода заполнения внутренней таблицы данными из базы или локаль- ными переменными программы:
• Считывание данных из таблиц баз с помощью команды select
* Добавление строк с помощью команды append
* Позиционная вставка строк с помощью команды insert
• Передача всей таблицы с помощью команды move
Эти методы подробно рассматриваются в последующих разделах.
Чтение данных из таблиц базы
Этот метод изложен в главе 11. Обычно результат запроса к базе данных помещается во внутреннюю
Таблицу, что реализуется посредством дополнения into table оператора select:
ralact * from customers t a b l e
В этом примере содержимое внутренней таблицы теряется при записи новых данных.
Однако иногда его требуется сохранить и добавить новые строки в конец таблицы. Это можно сделать с помощью дополнения appending table:
* from customers appending t a b l e
Как указывалось ранее, система АВАР/4 автоматически выделяет нужный объем памяти
для таблицы. Выделение памяти и роль параметра счетчика Occurs Parameter рассматри-
вается в разделе "Размер внутренней таблицы".
Добавление строк
При работе с циклами select и внутренними таблицами, имеющими ограниченное представление базы данных, можно добавлять отдельные строки или блоки строк во внутреннюю таблицу.
возвращаясь к примеру туристического агентства, допустим, что необходимо построить таблицу, кото-

140 Глава 12
рая содержит только идентификационные номера клиентов и названия городов их проживания (т.е.
два поля в каждой записи из таблицы базы данных customers).
t y p e s :
of
id
customers-id,
city
customers-city,
end of
data:
type
occur» 100
with header
select
from
move-corresponding customers to
append

Как можно догадаться из названия, оператор append (добавление) просто добавляет содержимое строки заголовка в конец внутренней таблицы. В данном случае используется то обстоятельство, что таблица объявлена вместе со строкой заголовка. Например, если с помощью append добавляется строка заголовка из таблицы 12.2, то измененная внутренняя таблица customer_cities будет выглядеть следую- щим образом:
Таблица 12.2
Содержимое таблицы customer_cities после выполнения команды append
Строка заголовка
00000015 Dry Greek
Содержимое таблицы
00000001 Small Town
00000002 Village
00000017 Big City
87654321 Fort Myers
00000015 Dry Greek
Если в определении таблицы не задана строка заголовка, необходимо точно указать структуру от- дельной записи, чтобы обеспечить ее соответствие данной строке. В этом случае следует связать эту запись с рабочей областью (work area), которая и будет использоваться в операторе append:
data my_customer l i k e customers.
append my_customer to all_customers.
Каждый из описанных способов (использование строки заголовка и рабочей области) имеет свои сильные стороны. При работе со строкой заголовка не нужно объявлять внешнюю запись — средства
АВАР/4 делают это автоматически. Кроме того, такая запись оператора append более понятна. Однако,
если в программе применяются вложенные внутренние таблицы (таблицы внутри записей или других таблиц), следует воспользоваться рабочей областью, так как у вложенных таблиц нет строки заголовка.
Содержимое внутренней таблицы можно добавить к любой другой, используя дополнение lines of опе- ратора append. Например, к таблице ali_customers можно добавить внутреннюю таблицу old_customers:
data old_customers like customers occurs 10.
append lines of old customers to all_custoraers.
Задание диапазона добавляемых из исходной таблицы строк обеспечивается дополнением from x to у.
Добавление набора строк с помощью
of поддерживается
системе R/3, начиная
с Release 3.0C.
Позиционная вставка строк
Команда append заполняет таблицу в соответствии с последовательностью выполнения программы.
Однако часто требуется просто вставить одну или несколько строк в определенном месте таблицы. Для

Использование внутренних таблиц 141
этого используется оператор insert, который вставляет новые строки до указанного в нем номера, со- ответственно сдвигая последующие строки. Предположим, необходимо вставить новую, третью, строку таблицы:
i n s e r t
index
В таблице 12.3 показаны содержимое строки заголовка, которое будет добавлено к внутренней таб- лице (Header Line), и таблица, куда строка уже добавлена (Table Contents).
Таблица
Таблица customer_cities table
Header Line
00000005
Table Contents
00000001 00000002 00000005 00000017 67654321 00000015
Pleasant Site
Town
Village
Pleasant Site
Big City
Fort Myers
Dry Greek
Как и оператор append, insert допускает использование внешней рабочей области, указанной после дополнения from. Кроме того, возможна вставка набора внутренних таблиц за одну операцию. Для этого предусмотрены дополнения lines of и from x to у. Например, нужно добавить строки 2 — 5 из таблицы old_cities в таблицу customer_cities, которые будут вставлены как строки с номерами 3, 4, 5 и б, а преж- няя строка 3 таблицы customer_cities должна получить номер 7:
insert lines of
from 2 to 5
into
index
Обратите внимание, что позиционная вставка нескольких строк с помощью оператора insert с до- полнением lines of выполняется быстрее, чем вставка одной строки в цикле.
Добавление набора строк с использованием lines of поддерживается в системе R/3,
начиная с Release
Перемещение таблицы в целом
Команда move позволяет с помощью одной операции заполнить внутреннюю таблицу содержимым любой другой. В приведенном ниже примере оператор move пересылает всю внутреннюю таблицу в таблицу foreign_customers:
tables
like customers occurs
foreign_customers like
select *
customers into table a l l
move
to
Если внутренняя таблица имеет строку заголовка, то эта строка (но не сама внутренняя таблица!)
может быть скопирована с помощью move. В приведенном ниже типичном примере элемент таблицы базы данных и копируется в строку заголовка внутренней таблицы:
tables
data
h like customers occurs 100
with header
select single
from customers where id
move customers to
append
6 Зак. 65

142 Глава 12
В данном случае рабочая область таблицы customers пересылается в строку заголовка foreign_customers_h,
которая добавляется во внутреннюю таблицу.
Размер внутренней таблицы
Как упоминалось ранее, при разработке программы пользователю не нужно самостоятельно выде- лять память, поскольку АВАР/4 делает это автоматически. Например, заранее можно не определять максимальный размер внутренней таблицы. Единственное ограничение — размер виртуальной памяти компьютера, т.е. внутренняя таблица в действительности может содержать неограниченное число строк.
Однако заданный в программе максимальный размер внутренней таблицы значительно ускорит ее вы- полнение. В АВАР/4 количество строк таблицы определяется по значению параметра счетчика Occurs
Parameter (число, которое указывается после ключевого слова occurs в определении данных таблицы).
Вычисленный размер таблицы (в байтах) является главным фактором, влияющим на скорость выпол- нения программы, и определяется как произведение длины строки на количество строк в таблице:
estimated_size = width * number_of_lines.
Длина строки определяется как сумма длин всех составляющих полей одной строки. Например,
длина строки с 50 полями, каждое из которых имеет размер 4 байт, будет равна 200 байт.
Обычно при создании первого элемента таблицы система выделяет такой объем памяти, в котором можно разместить всю таблицу или по крайней мере блок размером 8-16 Кбайт. Таким образом, пра- вильно задав Occurs Parameter, можно избежать выделения системой избыточного объема памяти.
Число, задаваемое как параметр Occurs (точнее, правильное определение этого числа), играет особо важную роль, если в программе маленькие таблицы представляют собой части большой, имеющей много строк. Если Occurs Parameter установить слишком большим для мелких таблиц, входящих в боль- шую, то память будет расходоваться напрасно, так как для каждой строки большой таблицы система должна выделить как минимум 8 Кбайт. Очень крупные таблицы нельзя разместить целиком в непре- рывной области основной памяти, поэтому программа "перекидывает" некоторые части таблицы на диске в свои. Желательно не указывать Occurs Parameter для крупных таблиц, поскольку система всегда сама определяет свопинг, оптимальный с точки зрения использования памяти и времени центрального процессора.
Так как система выделяет память динамически (по мере необходимости), то при установке парамет- ра счетчика Occurs Parameter следует помнить, что:
• Параметр счетчика не влияет на фактический размер таблицы, он определяет только производи- тельность выполнения операций с ней.
• При невозможности определить размер таблицы установите значение параметра счетчика равным нулю. В этом случае система сама установит размер.
• Если предполагаемый размер таблицы менее 8 Кбайт (например, пять строк длиной по 100 байт каждая, т.е. 500 байт), значение параметра счетчика задайте равным вычисленному количеству строк.
• Если предполагаемый размер таблицы более 8 Кбайт, установите его равным нулю. В этом случае система сама установит размер таблицы.
Для очень больших внутренних таблиц (объемом, например, 10 Мбайт) лучше освободить необхо- димую память с помощью оператора free, который удаляет все строки, освобождая занимаемую ими память:
free all_customers .
Для удаления всех строк внутренней таблицы можно воспользоваться командой refresh, которая будет рассмотрена ниже. Память, отводимая для хранения локальных внутренних таблиц подпрограмм,
освобождается автоматически при возврате управления в вызывающую программу.
Сортировка элементов внутренней таблицы
При заполнении внутренней таблицы одним из перечисленных ранее способов порядок элементов в ней не определен. Однако удобнее работать с таблицей, элементы которой упорядочены согласно какому-либо критерию сортировки. Легче всего это сделать, использовав команду sort (сортировать),
простейшая синтаксическая форма которой приведена ниже:
data my_flights l i k e a c t f l i occurs 10.
s o r t my_f l i g h t s .
Порядок сортировки неявно определен последовательностью полей в структуре строки таблицы, т.е.
крайний левый столбец служит первым критерием сортировки.

Использование внутренних таблиц 143
В таблице 12.4 приведено содержимое таблицы my_flights того же туристического агентства до при- менения к ней команды сортировки.
Таблица 12.4
Неупорядоченная таблица my_flights
XYZ
ABC
ABC
XYZ
ABC
0007
1000
1234
0006
1234
19990505
19991230
19991231
19990606
19991230
110
200 300 100 500
USD
DEM
DEM
USD 1
DEM
133 110 020
75
010
В таблице 12.5 показано, как будет выглядеть та же таблица после сортировки согласно приведенной выше короткой программе.
Таблица 12.5
Содержимое таблицы my_flights после обработки командой sort
ABC
ABC
ABC
XYZ
XYZ
1000
1234
1234
0006
0007
19991230
19991230
19991231
19990606
19990505
200 500 300 100
110
DEM
DEM
DEM
USD
USD
110
010
020
175
133
Кроме того, возможна сортировка таблицы по нескольким указанным полям:
sort my_flights by fldate price.
В таблице 12.6 приведен вид той же таблицы my_flights после сортировки в соответствии с приве- денным выше критерием. Приоритетным согласно порядку записи в операторе является поле fldate, a внутри этой отсортированной таблицы происходит сортировка по полю price.
Таблица 12.6
Содержимое таблицы my_flights после сортировки по полям fldate и price
XYZ
XYZ
ABC
A8C
ABC.
0007
0006
1000
1234
1234
19990505
19990606
19991230
19991230
19991231
110
100
200 500 300
USD
USD
DEM
DEM
OEM
133 175 110 010 020
Существует также возможность сортировки в обратном порядке с помощью ключевого слова descend- ing (убывающий). По умолчанию порядок сортировки всегда возрастающий (ascending). Например, при- веденные ниже строки позволяют упорядочить таблицу сначала в порядке возрастания номеров идентификаторов, а затем отсортировать в порядке убывания стоимости билета (т.е. наименьший номер идентификатора окажется первым, а внутри этой последовательности первой будет максимальная цена).

144 Глава 12
Простейшая форма команды сортировки (без дополнений) обладает особым свойством: в
качестве критерия сортировки она использует только нечисловые поля, поскольку поля
первичного ключа обычно символьные (типа с, d или л). Если же поля для сортировки перечисляются
в явном виде, то данное ограничение не действует и таблица упорядочивается согласно указанной
последовательности полей, где первое поле является первым критерием сортировки.
Извлечение строк из внутренней таблицы
Когда внутренняя таблица будет заполнена и отсортирована, нужно выяснить, как вывести на экран ее содержимое. Для этого необходимы синтаксические структуры, позволяющие извлекать данные из таблиц построчно (считывая отдельную строку или их последовательность в цикле).
Получение всех строк внутренней таблицы
Программа для считывания строк в цикле может выглядеть так:
loop at
write /
Этот набор операторов выводит на экран фамилии всех клиентов внутренней таблицы all_customers
(с первого до последнего). Строка заголовка последовательно заполняется текущей строкой таблицы на каждом шаге цикла, т.е. система извлекает строку таблицы и размещает ее в строке заголовка, содер- жимое которой может меняться, не влияя на содержимое внутренней таблицы в целом.
Для внутренних таблиц можно использовать вложенные циклы, так же как и в операторах select для таблиц базы данных:
loop at
write /
loop at
write /
Во время выполнения цикла номер текущей строки всегда содержится в поле которое можно использовать внутри вложенных циклов, так как оно автоматически устанавливается равным номеру строки текущего активного цикла. Обычно в дальнейшем этот номер применяется для изменения или удаления строки.
Аналогично тому как это делается для предложения where оператора select, который описан в главе 11, можно ограничить цикл заданным подмножеством элементов внутренней таблицы, Для этого используется предложение where с заданным условием:
loop at
tamers
where name = ' Smith' .
write /
Предложение where может содержать все условные операторы, которые применяются для оператора if, например eq,
о, ge,
(см. пояснения в главе 9). Если, допустим, необходимо вывести на экран список всех клиентов, фамилии которых начинаются с буквы Е и которые не проживают в городе Small Town, можно применить операторы
(сравнение по шаблону) и
(не равно):
loop at all_customers
where name

Использование внутренних таблиц 145
and c i t y
' Small Town' .
write /
Кроме того, разрешается в явном виде задать интервал номеров строк (если он известен):
loop at all_customers
from 10 to 15.
Нижнюю или верхнюю границу выбранного интервала можно опустить. Если не указана нижняя граница, цикл будет выполняться с первой строки до заданной, а если не указана верхняя, — с заданной до последней строки таблицы.
Цикл по строкам внутренней таблицы, не имеющей строки заголовка, требует использования рабо- чей области для размещения содержимого текущей строки. Эта область задается с помощью дополнения into оператора loop:
data
customers.
loop at all_customers into
write /
Чтение отдельных строк
В общем случае существуют два метода чтения отдельной строки внутренней таблицы: путем прямого указания номера строки и задания строки посредством логического ключа. Оба метода поддерживаются командой table. Дополнение index со значением индекса элемента таблицы позволяет прочитать требуемый элемент:
read table all_customers index
if sy-subrc
write /
write / 'Customer not found'.
endif.
Третий элемент таблицы будет помещен в строку заголовка, если таблица содержит как минимум три элемента. В противном случае система возвратит не равную нулю системную переменную sy-subrc.
Используя дополнение into оператора read table, результат можно поместить в другую запись, как это делалось для цикла.
специально выделенная запись необходима, если таблица не имеет строки заголовка:
data my customer like
read table all_customers into
3.
Однако обычно номер строки в таблице заранее неизвестен. Поэтому возникает естественное жела- ние использовать содержимое элемента таблицы. В частности, если известны поля первичного ключа соответствующей таблицы базы данных, можно получить доступ к нужной строке внутренней таблицы с помощью дополнения with key, после которого указывается спецификация ключевого поля (или полей):
read table all_customers with key id • '87654321'.
if sy-subrc
write /
else.
write /
not
.
endif.
В случае успешного выполнения команда read возвратит индекс строки в системном поле
Так, если четвертая строка внутренней таблицы содержит то системное поле sy-tabix примет значение 4 и в строку заголовка будет записан соответствующий элемент. Команда table работает также с другими полями таблицы, которые выполняют роль ключевых. Например, если известны имя и город, где проживает клиент, то можно получить соответствующую запись в таблице,
используя оба поля в качестве ключевых:
read table
with key name
'
c i t y
'Big City'
if sy-subrc
0.
write: /
a l l

146 Глава 12
write / ' Customer not
.
В этом примере считывается запись таблицы относящаяся к человеку по имени Smith,
который живет в городе Big City. Заметим, однако, что этому условию удовлетворяют несколько кли- ентов; в данном примере их два — Robert Smith и
Smith. В приведенном варианте команда read table последовательно просматривает записи в таблице и цикл завершается после того, как окажется выполнено условие. Таким образом, будет извлечен первый встретившийся элемент, удовлетворяющий ключевому условию (например, поле
Smith, а не Robert Smith, если поля были отсортированы по имени клиента).
Если внутренняя таблица слишком велика, то последовательный поиск в ней происходит очень мед- ленно. Ускорить его можно, добавив в оператор чтения read table параметр binary starch (двоичный поиск).
Алгоритм двоичного поиска требует, чтобы элементы таблицы были отсортированы по указанному клю- чевому полю (это требование объясняется ниже). Так, если необходимо заполнить таблицу all_customers элементами, отсортированными по первичному ключу таблицы customers, программа двоичной сорти- ровки будет выглядеть следующим образом:
select from customers into table all_customers order by primary key.
read table with key id = '87654321' binary search.
if
= 0.
write /
else.
write / ' Customer not
.
endif.
При использовании алгоритма двоичного поиска система прежде всего проверяет соответствие ключу среднего элемента таблицы. Если условие удовлетворяется, двоичный поиск прекращается и про- исходит чтение. В противном случае поиск осуществляется в первой или второй половине таблицы, в зависимости от того, больше или меньше указанного ключевого поля уже проверенное значение. При этом вновь выбирается средний элемент из данной половины таблицы и проверяется соответствие ключу. Процесс повторяется до тех пор, пока не будет найдена (или ее не окажется вовсе) строка,
соответствующая ключу. В зависимости от результата системный код возврата sy-subrc устанавливается либо равным нулю (успешное завершение), либо не равным нулю.
Алгоритм двоичного поиска выполняется в АВАР/4 безусловно, независимо от того, отсор-
тирована таблица или нет. Ответственность за сортировку таблицы несет пользователь.
Если таблица неотсортирована, результат чтения может оказаться неправильным.
Допускается использование алгоритма двоичного поиска, если внутренняя таблица отсортирована не по первичному ключу, а по любому другому критерию:
sort all_customers by name city telephone.
read table all_customers with key name = ' Smith'
city = 'Big City'
telephone = '717-161-5151'
binary if sy-subrc = 0.
write /
else.
write / ' Customer not endif.
В общем случае, если приходится считывать по одной строке большой таблицы в
произвольные моменты выполнения программы, эти таблицы полезно хранить отсортиро-
ванными. Всегда можно заполнить таблицу так, чтобы она была предварительно упорядочена по
первичному ключу. Однако, если обычно используется циклическое чтение всех строк таблицы,
сортировать ее нет необходимости.

Использование внутренних таблиц 147
Внесение изменений во внутреннюю таблицу
В предыдущих разделах описывалось, как заполнить внутреннюю таблицу и прочитать из нее одну или несколько строк. В данном разделе рассматривается внесение во внутреннюю таблицу —
модификация существующих строк, добавление новых и удаление одной или нескольких строк.
Вставка нескольких строк
Предположим, необходимо найти элемент отсортированной таблицы, используя команду read по
(with key) и алгоритм двоичного поиска (binary search). Если элемент не найден, код возврата системы будет не равен нулю. В системном поле содержится указатель на строку,
рая следует за применяемым при задании ключевого условия (если таковой имеется в лице). Этот указатель можно использовать для вставки нового элемента с помощью команды insert.
Например, нужно добавить данные о новом клиенте во внутреннюю таблицу содержимое которой приведено в таблице 12.8.
Таблица 12.8
00000001 00000002 00000017 87654321
Edwards
Young
Smith
Edison
Small Town
Village
City
Fort Myers
654-321-1234 717-161-5151 111-111-1111
table
with key id
'00000005' binary search.
if
0.
- '00000005'.
'Martinez' .
= ' Phoenix' .
=
insert a l l customers index sy-tabix.
После выполнения оператора чтения системное поле sy-tabix окажется равным 3, поэтому новое поле будет вставлено перед строкой и таблица alLcustomers станет такой, как показано в таблице 12.9.
Таблица 12.9
00000001 00000002 00000005 87654321
Edwards
Young
Martinez
Smith
Edison
Small Town
Village
Phoenix
Big City
Fort Myers
654-321-1234 333-444-2222 354-321-4567 717-161-5151 111-111-1111
Используя дополнение into, можно вставить во внутреннюю таблицу содержимое отдельной рабочей области. Кроме того, как указывалось ранее, для вставки нескольких внутренних таблиц с помощью одного программного оператора применяется дополнение from x to у.
Модификация одной строки
Строки внутренних таблиц можно модифицировать. Обычно строка, которую нужно изменить, сна- чала считывается, затем в нее вносятся изменения, и она записывается в таблицу. Например, необхо-

146 Глава 12
димо изменить строку 00000005 таблицы all_customers. Для этого существует команда modify, которая использована в следующем примере:
t a b l e with id = '00000005' binary search.
if
= 0.
' Big City' .
modify all_cuatomers index
Как и append, оператор modify позволяет использовать рабочую область, указанную после дополне- ния from. Изменение единственной строки внутри цикла не требует указания номера ин- декса строки, так как система применяет текущее значение индекса.
Предположим, код области для Big City изменился с на 777 и в соответствии с этим необходимо откорректировать внутреннюю таблицу:
loop at where c i t y = ' Big City' .
' 7 7 7 ' .
Дополнение from позволяет изменить строку внутренней таблицы с помощью отдельной рабочей области.
Удаление нескольких строк
Аналогичным образом можно удалить одну строку внутренней таблицы, зная ее положение в таблице:
read table with key id
'00000005' binary search.
if
' Big City'
delete
index
Команда delete, как и команда modify, применяется для удаления единственной строки внутри цикла loop/endloop и не требует от пользователя указания номера индекса строки. Несколько внутренних таблиц можно удалить с помощью одного программного оператора, используя предложение where или указывая диапазон строк посредством дополнения x to у. Например, нужно удалить из таблицы записи всех клиентов, чьи фамилии начинаются на букву Е:
d e l e t e where name
' E * ' ,
Для удаления всех строк таблицы с помощью одного оператора следует использовать оператор re- fresh (обновить):
r e f r e s h
Если внутренняя таблица имеет строку заголовка, то команда refresh не изменяет ату строку и последняя может быть заново инициализирована с помощью команды clear (установить в исходное положение).
Локальные внутренние таблицы, определенные в подпрограммах (формах или функциях), автомати- чески удаляются системой после завершения выполнения подпрограмм. В этом случае оператор refresh будет избыточным. Однако статические внутренние таблицы (определенные как statics) остаются неиз- менными и впоследствии могут быть использованы данной подпрограммой.
Работа с промежуточными суммами
Промежуточные суммы, заголовки и т.п., относящиеся к группе элементов внутренней таблицы,
можно получить, используя в цикле группы команд at и endat (начало и конец
Операторы,
находящиеся между соответствующими командами at и endat, обрабатываются следующим образом:
• at first/endat — в начале каждого доступа к таблице
• at new f/endat — если содержимое поля f или одного из предшествующих полей было только что изменено
• at end
— если содержимое поля i иди из предшествующих полей будет изменено на следующем шаге
• at
— по завершении работы с таблицей

Использование внутренних таблиц 149
Приведенная ниже программа иллюстрирует использование новых операторов. Внутренняя таблица заполняется из базы данных, и для каждого элемента на экран выводится количество забро- нированных мест. Дополнительно отображаются заголовки и промежуточная сумма забронированных мест для каждой транспортной компании:
Извлечение данных
Строки внутренней таблицы всегда имеют одинаковую структуру. Извлечение групп полей позволяет не только обрабатывать наборы данных с различной структурой, но и производить статистические опе- рации над структурированными данными.
Например, необходимо получить статистические данные о пунктах назначения рейсов различных авиакомпаний (содержащихся в таблицах и
В частности, нужно вывести на экран началь- ный и конечный пункты каждого маршрута и число забронированных мест для всех рейсов авиакомпа- нии на данном маршруте.
Первый способ сделать это — определить в Dictionary представление таблиц planfli и actfli и внут- реннюю таблицу, имеющую структуру данного представления. Однако при таком подходе внутренняя таблица будет содержать много избыточной информации, а это при больших исходных таблицах может создать серьезные проблемы.
Извлечение групп полей позволяет более эффективно решать подобные задачи. В принципе этот метод имитирует внешнее соединение таблиц и временно сохраняет результат в виртуальной памяти с помощью команды extract. В рамках набора извлеченных данных можно осуществлять сортировку и вычислять любые статистические характеристики для каждой группы данных.
Процесс извлечения данных подразделяется на несколько шагов. На первом необходимо задать кри- терии сортировки для всех структур и контейнеров, прибегнув к определению field-groups в сочетании с разными вариантами команды insert. На втором шаге следует сохранить в памяти ис- пользуя для этого команду extract. Затем набор данных можно упорядочить, применив команду сорти- ровки без каких-либо дополнений. На последнем шаге с помощью конструкции последовательно считываются все элементы. Статистические характеристики вычисляются внутри цикла посредством группы команд
Для правильного выполнения конструкций at new f и at end f следует иметь дело только с таблицей,
отсортированной хотя бы по полю, предшествующему f. В противном случае необходимо использовать локальное поле для хранения содержимого поля f предыдущего элемента.

150 Глава 12
В команде sort нет необходимости указывать имя
извлекаемых данных, поскольку
программа при выполнении может извлекать только один набор контейнеров. Группы
команд
могут использоваться так же, как и для внутренних таблиц (см. предыдущий раздел).
Вложенные таблицы
Все операторы, применяемые при работе с внутренними таблицами, подходят и для вложенных таб- лиц. Напомним, что таблицы, вложенные в запись или в другую таблицу, не имеют строки заголовка.
Поэтому предпочтение следует отдать тем командам, которые не используют строки заголовка.
Предположим, что вложенные таблицы применяются для связи между конечными пунктами и для полетов:
В первой части примера поля критерия сортировки вставляются в группу полей header. Это специ- альная группа полей, предназначенная для критериев сортировки, всегда должна присутствовать под указанным именем. Кроме того, соответствующие структуры контейнеров данных задают группы полей connections и flights. На следующем шаге контейнеры записываются в виртуальную память при помощи команды extract, для чего организован вложенный цикл select. Критерий сортировки группы полей автоматически записывается каждым оператором extract. Затем извлеченные данные упорядочи- ваются посредством простого оператора sort. Завершает программу чтение в цикле всех извлеченных данных. Сумма забронированных мест вычисляется для всех рейсов каждой транспортной компании,
так как включена в соответствующие операторы
В отличие от внутренних таблиц, в данном случае групповая логика блока подчиняется порядку, определенному в команде sort. Этот порядок может отличаться от статической структуры за- головка группы полей, обеспечивая дополнительные возможности при извлечении данных.

Использование внутренних таблиц 151
Обратите внимание, что применение вложенных таблиц служит альтернативой технике извлечения данных с помощью иерархических наборов. В общем случае использование внутренних таблиц более широкие возможности.
Резюме
• Одним их важнейших инструментов языка АВАР/4 являются внутренние таблицы с произвольным числом строк и динамическим управлением распределением памяти.
• Если используется таблица без строки заголовка, необходимо предусмотреть запись для хранения содержимого текущей строки.
• Таблицы заполняются данными с помощью команд select, append, insert и move.
• Предварительный размер таблицы указывается в операторе data посредством параметра счетчика Oc- curs Parameter, причем разработчик может не заботиться об объеме занимаемой таблицей памяти.
• Команда sort сортирует таблицу по указанным полям.
• Используя цикл с предложением where, можно последовательно считывать наборы или поднаборы строк.
• Для изменения строк служат команды insert, modify или delete. Команда refresh удаляет все строки таблицы,
• Групповая логика поддерживается различными блоками at/endat в циклах.
• Извлечение данных позволяет обрабатывать группы отобранных данных различной структуры и собирать статистическую информацию по сгруппированным данным.
• Многоуровневые таблицы обрабатываются так же, как и плоские, однако при работе с ними нужно предусматривать отдельную запись для работы с вложенной таблицей.
Изучив команды для манипулирования данными внутренних таблиц, можно перейти к следующей главе, где описаны операции для изменения таблиц базы данных. Следует заметить, что работа с вло- женными таблицами трех и более уровней — очень непростое занятие.
Используя вложенные циклы, можно прочитать все строки внешней и внутренней (flight)
таблиц:

1   ...   7   8   9   10   11   12   13   14   ...   24


написать администратору сайта