Р. Кречмер, В. Вейс - Разработка приложений SAP R3 на языке АВАР4. Р. Кречмер, В. Вейс - Разработка приложений SAP R3 на языке АВАР. Разработкаприложений sap r3Рюдигер Кречмерна языкеВольфганг Вейс
Скачать 28.36 Mb.
|
Глава 10 Нa появившемся экране введите имя функции в строке для ввода текста, соответствующей модулю функции — Function Module (в нашем примере MY_FIRST_FUNCTION). и щелкните мышью на кнопке Create (создать) согласно рис. 10.2. Затем укажите атрибуты функции (рис. 10.3). В нашем примере описание функции в окне Short Text (краткий текст) задано как This is my first function, но группа функции еще не выбрана. Функциональные группы рассматриваются в следующем разделе. В данном случае для Process Type (выполнение) выбрана группа Normal (обычная). Рис. 10.2 Создание функции Рис. 10.3 Задание атрибутов функции Функциональная группа представляет собой контейнер, включающий одну или несколько связанных между собой функции. В частности, все функции в функциональной группе используют одни и те же формы, которые определены в этой группе. Типичными примерами функциональных групп являются группы печати документов, обновления записей в бухгалтерских книгах или чтения информации состав- ных финансовых документов. Полный обзор всех функциональных групп приводится на экране создания функциональных модулей (Function Module Create). Доступ к нему можно получить, установив курсор на входное поле Function Подпрограммы и функции 117 Group и щелкнув мышью на кнопке Possible Entries (допустимые функции), расположенной справа от этого поля (или нажав клавишу F4). На экране появится всплывающий список, подобный показанному на рис. 10.4. Рис. 10.4 Допустимые функции функциональных групп Кроме того, совместно используемые подпрограммы и функции в функциональной группе могут об- ращаться к общим глобальным данным группы. Этим можно воспользоваться при программировании работы с диалоговыми окнами и целыми экранами, отображаемыми некоторыми функциями (см. главы 19 и 22, где подробно описаны диалоговые экраны). С точки зрения техники программирования функциональная группа представляет собой программу, со- стоящую из нескольких файлов типа Include, каждый из которых соответствует отдельной функции. Когда при выполнении программы вызывается одна из функций, вся функциональная группа загружается в основ- ную память и функция выполняется. После этого функциональная группа остается в памяти, т.е. она по- вторно не загружается головной программой текущего процесса при вызове другой функции группы. Для того чтобы связать функцию с новой функциональной группой, нужно просто ввести новое имя функциональной группы во входное поле Function Group (функциональная группа) на экране, который показан на рис. 10.3. При этом система запросит, хочет ли пользователь создать новую группу. В случае положительного ответа пользователю предоставляется возможность на следующем экране ввести крат- кое описание группы и имя лица, ответственного за нее (рис. 10.5). Рис. 10.5 Задание функциональной группы 118 Глава 10 Интерфейсные параметры Параметры функции подразделяются на импортируемые, экспортируемые и изменяемые. В операто- ре call function список формальных параметров расположен слева от знака равенства, а список факти- ческих - справа. Порядок параметров в операторе вызова не играет роли, так как фактические параметры идентифицируются по именам формальных. Значение дополнений importing и exporting за- висит от того, где они употребляются — в вызывающей или в вызываемой функции. Они меняются ролями при определении и вызове функции. Изменяемые параметры представляют собой комбинацию экспортируемых и импортируемых параметров. Предположим, нужно написать функцию для преобразования температуры — из градусов по шкале Фаренгейта в градусы по шкале Цельсия. Подобная функция имеет один импортируемый параметр, который позволяет различить тип шкалы (Фаренгейта или Цельсия) и один параметр для значения температуры. Экспортируемый параметр будет содержать преобразованную величину. f u n c t i o n 'CONVERT_TEMPERATURE'. Local * value (temp_unit) type с * value (degrees) type p * exporting reference type p if temp_unit = ' = ( degrees - 32 ) * 5 / else. = degrees * 9 / 5 + Этой функции соответствует следующий вызов: data deg type p. function exporting temp_unit F' degrees • 100 importing conv_degrees = Передача параметров значению и по ссылке синтаксически различается по дополнениям value (p) и reference (p). Как и для форм, эти различия указываются только при определении функции. При работе с параметрами функции всегда используется специальный экран АВАР/4 Development Workbench. Чтобы получить к нему доступ, нужно последовательно указать элементы меню: Goto > на любом экране, где редактируется или отображается функция (рис 10.6). Рис. 10.6 Переход к интерфейсным параметрам из экрана сопровождения атрибутов Maintenance Подпрограммы и функции 119 Рис. 10.7 Задание интерфейсных параметров Для каждого параметра можно задать тип, указав ссылку на структуру или на поле в Dictionary, или применить прямую ссылку на тип, как показано на рис. 10.7. В последнем случае он должен либо являться элементарным типом АВАP/4 (с, n, i, p, d и т.д.), либо быть определен в Dictionary (см. главу 5). Когда вызывающая программа не устанавливает значение импортируемого и изменяемого парамет- ров явным образом, его можно задать по умолчанию. Значение по умолчанию может быть введено в столбце Proposal. Импортируемые (если их рассматривать с функциональной точки зрения) и изменяемые параметры могут быть отнесены к разряду необязательных (рис. 10.7). В этом случае в вызывающей программе необя- зательно передавать значение этого параметра, поскольку программа присваивает ему начальное значение соответствующего типа. Параметры, значения которых указаны в столбце Proposal, всегда необязательны. Если специально не оговорено, что исходный параметр необязателен, он должен быть задан в вызывающей программе; в противном случае при выполнении возникнет ошибка. Экспортируемые параметры считаются результатом работы функции и могут не присутствовать в вызывающей программе. В интерфейсе функции разрешается использовать внутренние таблицы, которые всегда вызываются по ссылке (чтобы не снижать производительности программы). Из любого экрана сопровождения функ- ции можно получить доступ к работе с параметрами внутренней таблицы (рис.10.8), выбрав элементы Рис. 10.8 Таблица параметров и исключений 120 Глава 10 линейки меню: Goto Tab./Exc.Interface. На этом же экране можно задать исключения, которые будут рассмотрены в следующем разделе. Исключения Так как функции обычно вызываются несколькими программами, в них не всегда можно, предусмот- реть обобщенную обработку ошибок или непредсказуемые события. Вместо этого в подобных случаях выполнение функции прекращается, а в вызывающую программу поступает соответствующее сообщение Данную технологию можно реализовать с помощью исключений. Доступ к экрану для задания исклю- чений осуществляется при выборе элементов линейки меню: Goto > Tab./Exc.Interface из любого эк рана сопровождения функции (рис. 10.9). Рис. 10.9 Экран для определения исключений Исключения можно задать, используя команду raise (установить). Как только эта команда начинает обрабатываться, выполнение функции немедленно прекращается, а в вызывающей программе можно определить соответствующее исключение по его имени. function Local * importing value like customers-name * tables structure customers * exceptions select customers into table where name = if sy-subrc raise Данную функцию можно вызвать следующим образом: c a l l function exporting = tables - exceptions = 1. if sy-subrc = write not Подпрограммы и функции 121 Выполнение оператора raise not_found завершает функцию. В самом общем случае обработка ситуа- ции, связанной с исключением, может выполняться как самой функцией, так и вызывающей ее про- граммой и зависит от способа вызова данной функции. Если в вызывающей программе исключениям присвоены специальные номера, то каждое из них записывает присвоенное ему значение в системный код возврата sy-subrc. Выполнение функции завершается, а вызывающая программа может определить, как продолжить работу. В противном случае происходит ошибка выполнения и вызывающая программа не реагирует на событие. Исключения можно сгруппировать, используя для разных исключений одинаковый код возврата: c e l l f u n c t i o n . . . = 1 invalid = 1 unlikely = 2. if = write 'Error'. alsexf sy-subrc write ' Unlikely case' . Кроме того, для обработки в вызывающей программе любого исключения предусмотрено стандарт- ное исключение others (другие): call function . . . exceptions not_found = 1 others 2. Стандартное исключение others предназначено для обработки всех исключений, которые неявно предполагаются в вызывающей программе. Помимо этого, можно задать дополнение raising оператора message (данный способ рассматривается в главе 20). Исключения разрешено задавать внутри подпрограмм (форм), входящих в функцию. В этом случае очищается стек вызовов форм и выполнение функции прекращается. Редактирование функции Для редактирования исходных текстов функции следует выбрать элемент меню Function Module (мо- дуль функции) на экране Function Module Create: Administration (создание модуля функции: администри- рование). Экран редактирования функции показан на рис. 10.10. Рис. 10.10 Редактирование функции 122 Глава 10 ДЛЯ вызова функции укажите элементы меню: Edit Statement (вставить оператор) на экране АВАР/4 Editor (см. раздел "Основные операции редактирования" главы 3). В появившемся диалоговом окне (рис. 10.11) введите имя функции в поле для ввода текста Call Function (вызов функции). По завершении этого шага все параметры и исключения интерфейса, а также значения по умолча- нию автоматически установятся в строке исходного текста функции, начиная с позиции курсора, от которой вы перешли к выполнению команды Insert (рис. 10.12). Рис. 10.11 Вставка оператора вызова функции Рис. 10.11 Оператор вызова функции, вставленный системой в исходные тексты Вызовы подпрограмм (форм) и функций могут быть вложенными, и в них разрешается использовать локальные данные. Однако применение вложенных определений форм или функций не допускается. Вложенные вызовы и завершения подпрограмм и функций Подпрограммы и функции 123 Если оператор form одной подпрограммы расположен до завершения определения другой (т.е. до опе- ратора внешней формы), то синтаксический контроль выдает ошибку. Подпрограммы являются глобальными внутри программы, а все функции определяются как глобальные для системы R/S. Система поддерживает также рекурсивные вызовы. Однако во избежание возникновения бесконеч- ных циклов условие завершения рекурсии следует задавать как можно аккуратнее. Наиболее простой способ разрешения данной проблемы (бесконечных циклов) в АВАР/4 — это использование команды exit (завершить), которая прерывает выполнение текущей формы или функции и продолжает выполне- ние внешней программы с фактического оператора perform или call fanction: number i value i value perform factorial. write if number <= 1. result result * number number После выполнения программы поле result будет содержать факториал заданного значения number. Оператор exit очень удобен также при создании больших подпрограмм, которые не имеют рекур- сивных вызовов. Однако всегда следует помнить, что команда exit относится только к данному блоку программных текстов, а выполнение программы будет продолжено с первого оператора, расположен- ного после этого блока. Ниже приведен список пар команд, выполнение которых не вызывает выхода из данного программного блока (например, если происходит выход из цикла, то выполнение передается на следующий после endloop оператор). Безусловный цикл (do/enddo) Условный цикл Подпрограмма 4. Функция 5. Чтение элементов таблицы базы данных (select/endselect, см. главу 11) 6. Чтение строк внутренней таблицы см. главу 12) Команда exit является контекстно-зависимой и всегда относится к внутренней структуре вложенных программных объектов (оказывает действие на самый внутренний программный объект). Резюме • Формы и функции обеспечивают модульный принцип программирования. Формы создаются для одной программы, а функции являются программным элементом, который вызывается нескольки- ми программами. • Локальные данные могут использоваться только в том программном блоке, где они определены (в пределах видимости). • Статические переменные представляют собой локальные данные, значения которых сохраняются внутри подпрограммы при повторных вызовах. • Каждому объекту интерфейса форм и функций должен быть присвоен определенный тип (с по- мощью определений type или data). Назначение типов обеспечивает контроль соответствия типов в процессе синтаксической проверки или во время выполнения. • Параметры формы или функции могут быть изменяемыми или только для чтения. Допускается передача фактических параметров как по значению, так и по ссылке. • При вызове все параметры формы должны быть записаны в том же порядке, в каком они пере- числены в ее определении. 124 Глава 10 • Внутри функции не обеспечивается доступ к глобальным данным вызывающей программы. Она работает только с интерфейсными параметрами и собственными локальными данными или с гло- бальными данными своей функциональной группы. • Функции поддерживают назначение параметров значений по умолчанию, статуса необязательных, а также обеспечивают исключения. • Вызовы форм и функций могут быть вложенными и даже рекурсивными. • Команда exit прекращает выполнение формы или функции. При этом программа продолжает выпол- няться с того оператора, который следует за оператором, вызывающим эту форму или функцию. В части IV рассматриваются возможности работы с таблицами баз данных и внутренними таблица- ми, а следующая глава посвящена чтению таблиц базы данных. Часть IV Работа с таблицами Глава 11. Чтение таблиц базы данных Глава 12. Использование внутренних таблиц Глава 13. Обновление таблиц базы данных Глава 14. Экспорт и импорт составных объектов данных Глава 11 Чтение таблиц базы данных Выборка данных из базы данных Динамическая выборка Первичные ключи и представления 128 Глава 11 В этой главе описывается использование оператора select для чтения таблиц базы данных как целиком, так и в режиме последовательного чтения записей. Для выборки данных, удовлетворяющих определенным условиям, применяется предложение where. Эти условия могут быть непостоянными для программы, дина- мически изменяясь во время ее выполнения. Такой режим тоже обсуждается в главе 11. Кроме того, в ней будет показано, как строить сложные запросы, включающие несколько таблиц (с помощью вложенных цик- лов select или представлений, определенных в АВАР/4 Dictionary). Конец главы посвящен различным спо- собам повышения производительности при реализации сложных запросов. Для демонстрации основных возможностей операторов SQL и способов работы с внутренними таб- лицами используется учебная модель данных туристического агентства из главы б, которую имеет смысл повторно просмотреть. Построение простейшего запроса Предположим, таблица customers из примера с туристическим агентством содержит информацию, представленную в таблице 11.1, а таблица bookings — информацию, записанную в таблице 11.2. Таблица 11.1 Пример содержимого таблицы customers 00000001 00000002 00000017 Edwards Young Smith Edison Small Town Village Big City 654-321-1234 333-444-2222 717-161-5151 111-111-1111 Таблица 11.2 Пример содержимого таблицы bookings ABC ABC ABC XYZ XYZ 1000 1234 1234 0006 0007 19991230 19991231 19990606 19990505 001 002 005 008 009 00000017 00000002 00000001 87654321 19990101 19991229 19990101 19990101 19990101 Представим, что читатель занимает должность агента в этом туристическом агентстве, а все его данные о клиентах содержатся в таблице customers, которая была описана в АВАР/4 Dictionary. Про- стейший способ получить список всех клиентов — написать следующую программу на АВАР/4: tables s e l e c t from / Эта программа выбирает все записи из таблицы базы данных customers и выводит на экран фамилию каждого клиента. Когда в программе указывается ключевое слово tables, за которым следует название таблицы базы данных, к объекту данных (называемому также рабочей областью) приписывается структура таблицы в том виде, в каком она была определена в Dictionary. Операторы select/endselect образуют цикл, где каждая строка таблицы базы данных помещается в рабочую область customers. Звездочка в операторе select означает, что выбираются все поля таблицы. Вместо использования рабочей области по умолчанию для записей таблицы можно выбрать другой объект. tables data my_customer like "alternative work area" s e l e c t customers into my_customer. Чтение таблиц базы данных 129 / Первый вариант (использование рабочей области по умолчанию) предпочтителен для небольших программ, считывающих таблицу базы данных только один раз. Второй вариант (использование отдель- ной рабочей области, указанной разработчиком) рекомендуется в тех случаях, когда для размещения элементов одной таблицы необходимо применять различные объекты данных. Например, если нужно сравнить разные значения из одной и той же таблицы агентства, то понадобится несколько различных рабочих областей. В частности, такая ситуация возникает при чтении двух последних заказов клиента: в одной области запоминается последний заказ, а другая требуется для работы с предыдущим. Обычно все объявления tables записаны в начале области определения данных и, кроме того, они отображаются браузером Object Browser в Development Workbench среди объектов программы, входящих в Dictionary. Для краткости в приведенных ниже примерах иногда будет пропущено tables. Простейшие операторы select для выборки данных Кроме описанного выше простейшего запроса АВАР/4 обеспечивает различные расширения опера- тора select, которые позволяют напрямую задать некоторый набор извлекаемых данных. Работа со всеми элементами таблицы Используя все тот же пример программы для туристического агентства, рассмотрим различные спо- собы чтения таблиц базы данных. Вместо того чтобы считывать один экземпляр данных за другим, можно с помощью одного оператора скопировать содержимое всей таблицы во внутреннюю а затем, организовав цикл, вывести каждую строку на экран: data customers occurs 100 with header line. select * customers into table loop at / В результате будет получен "моментальный снимок" таблицы базы данных. Для чтения каждой стро- ки внутренней таблицы была использована конструкция цикла loop/endloop, которая будет подробно рассмотрена в главе 12. На первый взгляд оба примера выполняют одну и ту же функцию: считывают данные из базовой таблицы и выводят на экран каждую строку. Однако способы, примененные в этих примерах, сущест- венно различаются: • Конструкция select/endselect работает с отдельным элементом таблицы, т.е. при извлечении каж- дого элемента выполняется одна операция. • Команда select into table считывает набор элементов, которые впоследствии можно обрабатывать. Для использования отдельных строк внутренней таблицы необходимо организовать дополнитель- ный цикл. Очевидно, что первый способ предпочтительнее в случае, когда каждый элемент таблицы применя- ется в программе один раз, а второй — если в дальнейшем предстоит неоднократная обработка набора элементов. Например, после выполнения цикла можно сортировать внутреннюю таблицу, вычислять сумму или другие статистические характеристики, а также удалять или модифицировать эле- менты внутренней таблицы, оставляя неизменной таблицу базы данных. Операции с внутренними таблицами рассматриваются в главе 12. Однако при достаточно большом наборе элементов таблицы применение второго способа может значительно снизить производительность приложения, даже если выполняется только операция чтения. Эта проблема обсуждается далее в разделе "Внешние ключи и представления", где рассматриваются вло- женные операторы select и представления. 130 Глава 11 Оператор select into table выполняется корректно, если внутренняя таблица меньше таблицы базы данных. Внутренняя таблица, помимо полей, определенных для таблицы базы в Dictionary, может содержать дополнительный правый используемый для хранения флагов или другой информации. Использование предложения where В приведенных выше примерах оператор select относился ко всем элементам таблицы независимо от их содержимого. В реальной жизни обычно приходится использовать некое подмножество элемен- тов, удовлетворяющее определенному условию. Например, все закалы клиентов на дату 01/01/1999: data bookings occurs s e l e c t * from bookings i n t o table where order_date • '19990101'. В данном случае предложение where ограничивает набор извлекаемых записей теми элементами, для которых дата заказа 01/01/1999. Согласно синтаксису название поля указано слева от знака равенства, а значение для сравнения — справа. В самом общем случае условие предложения where состоит из трех компонентов: поля таблицы, оператора сравнения и сравниваемого значения, В приведенной ниже таб- лице представлен список допустимых операторов, соответствующие им математические символы и опи- сание выполняемой операции. Описание операции равно не равно меньше чем меньше чем или равно больше чем больше чем или равно интервал шаблон равно а или b или с условие задается пользователем с помощью операции Select-Option Некоторые условия можно использовать совместно, применяя логические операторы and и or. На- пример, необходимо извлечь все заказы клиентов, сделанные после 01/01/1999, с идентификатором клиента 87654321: s e l e c t from bookings into table where - '87654321' and order_date >= '19990101'. Кроме того, часто бывает нужно создать запрос, содержащий шаблон для поиска, к примеру, всех клиентов, фамилия которых начинается на букву Е. Реализуется это с помощью оператора like: s e l e c t customers into table where name like Символ процента указывает, что за Е могут следовать другие символы, т.е. условию удовлетво- ряют фамилии Edwards, Edison, но не Для задания маски единственного символа применяйте подчеркивание (_). Например, при поиске клиента с фамилией типа Bell следует использовать маску которая позволит получить фамилии Ball и т.п. Использование дополнения in с составным критерием выборки Select-Options обеспечивает динами- ческое применение предложения where. Так, из существующего отчета легко можно получить необхо- димый набор данных, не изменяя исходного текста и не создавая нового отчета. Применение критериев типа Select-Options подробно рассматривается в разделе "Динамическая выборка данных". Система R/3 подразделяется на несколько Clients (клиент), где каждый Client представляет принад- лежность данных к одному из подразделений предприятия. Принадлежность к Client отражается в таб- лицах приложения, содержащих поле типа размещаемое в крайнем левом столбце (см. главу 5). При чтении данных из такой таблицы с помощью команды select нельзя назначить Client в предложе- нии where, поскольку система автоматически использует Client, которому принадлежит таблица. Оператор eq between a and b like in (a,b,c) in selopt = <> < <= нет символа нет символа нет символа нет символа Чтение таблиц базы данных 131 Чтение единственного элемента таблицы При чтении единственного элемента таблицы всегда применяется команда select single и предложе- ние where, где указаны все поля первичного ключа. После ее выполнения системный код возврата sy- subrc указывает на успешное (значение равно нулю) или неуспешное (значение не равно нулю) завершение запроса к базе данных: Извлечение единственного поля В предыдущих примерах с помощью звездочки (*) в операторе select извлекались все элементы таб- лицы со всеми полями. Однако иногда нужны не все поля элемента, а только какое-то их подмножество. Указать необходимые поля можно с помощью списка конкретных имен полей (например, id и name), который должен следовать сразу же после команды select. Соответствующие им поля программы (на- пример, cid и cname) перечислены после слов into в круглых скобках. В результате поле count_bookings будет содержать количество элементов, удовлетворяющих условию where. Точно так же, используя приведенные ниже дополнительные операции, можно получить и другие статистические оценки элементов таблицы: • max — максимальное значение в заданном столбце • min — минимальное значение в заданном столбце • avg — среднее значение в заданном столбце • sum — сумма значений заданного столбца Выполнив, например, следующую программу, можно получить из базы данных туристического агент- ства среднее число заказанных и максимальное число имеющихся мест: Обратите внимание, что оператор select single выполняется правильно только в том случае, если все поля первичного ключа заданы как единичные значения (т.е. с помощью операторов = или eq). Указание полей удобно для ограничения размера памяти, занимаемого объектами данных в программе. Например, если считываются 10 000 элементов таблицы, содержащей 100 полей в каждом элементе, из которых необходимы лишь два или три поля, то количество данных и время запроса, а также исполь- зуемые системные ресурсы можно существенно уменьшить, воспользовавшись выбором только указан- ных полей. Получение статистической информации Иногда бывает необходимо вычислить количество элементов таблицы, удовлетворяющих определен- ному условию. Получить это число можно, добавив в оператор select операции count(*) (сосчитать): 132 Глава 11 Если предполагается сортировать полученный список по ключевым полям таблицы базы данных, используйте дополнение order by primary key. В приведенном выше примере это приведет к упорядо- чению списка клиентов в соответствии с их идентификаторами. Динамическая выборка данных До сих все конструкции операторов select рассматривались статически, т.е. в предположении, что известны имена таблиц или точные условия для предложения where. Однако для некоторых задач на момент написания программы неизвестно имя таблицы или точные условия в предложении where. АВАР/4 предлагает несколько способов решения этой проблемы. Использование составных критериев выборки Select-Options В простейшем случае известно все, кроме логической структуры условий предложения where (т.е. известны имена таблицы и полей, но неизвестен оператор сравнения). Типичным примером этого слу- жит запрос конечного пользователя для выборки данных, сделанный до создания отчета и считывания базы данных. Средства для создания отчетов АВАР/4 имеют стандартный пользовательский интерфейс (жран выбора - selection screen), который обеспечивает задание любого критерия и условия. При работе программы заданные пользователем критерии выборки данных доступны в переменных, определенных как параметры Select-Options, которые определяют извлекаемый из базы набор данных. Приведенная ниже программа предлагает пользователю экран для ввода критерия выборки в Select- Options, а затем оператор Select считывает набор данных согласно заданному критерию: Более подробно использование средств Select-Options рассматривается в главе 16. Динамическое присвоение имен таблиц Допускается также динамическое присвоение имен таблиц, позволяющее каждому пользователю дать имя таблице, из которой извлекаются данные. При этом имя таблицы внутри оператора select заклю- чается в круглые скобки и следует сразу же за параметром from: Упорядочение результатов запроса В самом общем случае оператор select извлекает набор данных, однако средства СУБД не предус- матривают специального упорядочения получаемого набора. АВАР/4 обеспечивает возможность сорти- ровки результатов запроса с помощью одного из приведенных ниже способов: • Добавления дополнительного предложения order by в оператор select • Сортировки внутренней таблицы, содержащей результаты запроса (см. главу 12) Если упорядочение элементов выполняется с помощью добавления дополнения order by оператора select, то за ним должны следовать имена сортируемых полей: Порядок задания критериев или имен в рамках Select-Options не влияет на порядок их извлечения из базы данных. Чтение таблиц базы данных 133 В данном примере будет использовано имя таблицы CUSTOMERS. Динамическое использование предложения where Аналогично динамическому присвоению имен таблиц коды, принадлежащие предложению where, в процессе выполнения могут быть извлечены из внутренней таблицы и в дальнейшем использованы для отображения условий предложения where. Предположим, имеется внутренняя таблица ' E % ' and c i t y ' S % ' Ее можно использовать в предложении where следующим образом: select from customers i n t o table where id between 1 and 999 and Данный оператор считывает записи обо всех клиентах с идентификаторами от 1 до 999, фамилии которых и связанные с ними города начинаются с букв Е и S соответственно. Существенно, что внутренняя таблица может содержать справа от сравнения только литералы или константы. Безусловно, динамическое использование оператора select обеспечивает большую гибкость програм- мирования. Однако программы при этом становятся менее читабельными. Кроме того, увеличивается вероятность ошибок, так как синтаксическую правильность динамического предложения where нельзя гарантировать заранее. Поэтому, если программе не требуется неограниченная гибкость, рекомендуется применять статические операторы SQL (включая Select-Options в предложении where). Внешние ключи и представления Объекты данных приложения существуют в виде таблиц в реляционной системе базы данных и часто связаны различными отношениями. Одно из наиболее важных - связь по внешнему ключу, когда эле- менты одной таблицы одновременно являются внешним ключом другой. Например, содержимое поля customid таблицы bookings представляет собой внешний ключ таблицы customers. АВАР/4 предлагает три способа получения всех элементов нескольких таблиц, связанных по внешнему ключу: • Чтение элементов таблиц с использованием вложенных циклов select, в которых связь по внеш- нему ключу описана в условии внутреннего предложения where • Чтение элементов таблиц в одну внутреннюю из соответствующего представления, определенного в Dictionary • Чтение элементов таблиц в несколько внутренних и применение дополнения all entries для задания связи по внешнему ключу. Для иллюстрации этих способов используем таблицы customers и bookings из примера модели дан- ных туристического агентства. Предположим, необходимо составить список всех клиентов, которые за- казывали билеты на самолет начиная с 01/01/1999. Кроме того, возможно, следует вывести на экран дату каждого рейса, на который были заказаны билеты для каждого пассажира. В этом случае итоговый список будет содержать следующие данные: Пассажир Дата полета Edwards 06/06/1999 Smith 12/30/1999 Smith 12/31/1999 Edison 05/05/1999 Получение данных с помощью вложенных циклов select Вначале будет проиллюстрирован метод использования вложенных циклов select, где отношение внешнего ключа записано во внутреннем предложении where: 134 Глава Эта небольшая программа обеспечивает формирование необходимого списка. Заметим, что внутрен- ний цикл select всегда определяется текущим клиентом внешнего цикла. Циклы select допускают вложе- ния более чем на двух уровнях, и оба цикла select в этом примере могут иметь обратный порядок вложения. Но если требуется вывести имена клиентов, не заказавших билет на 01/01/1999, то подходит только порядок вложения циклов, использованный в приведенной выше программе. Применение вложенных циклов select является прямым и достаточно простым в реализации при- емом. Однако это не всегда лучшее решение с точки зрения производительности, поскольку передача управления между программой АВАР/4 и СУБД требует значительных затрат процессорного времени на каждом шаге цикла select. На практике более предпочтителен подход, когда содержимое таблиц базы данных сначала записывается во внутренние таблицы и только после этого обрабатывается. Использование представлений Dictionary для получения данных С помощью представлений, определенных в АВАР/4 Dictionary, за одну операцию можно записать ре- зультаты запроса во внутреннюю таблицу всю выходную информацию операторов select). Предполо- жим, что представление для таблиц customers и bookings с именами столбцов и order_date было определено в Dictionary. Содержимое представления можно изобразить в виде таблицы U.S. Внутренняя таблица может быть заполнена с использованием представлений за одну операцию, а далее будут обрабатываться ее отдельные элементы. Результирующий список окажется таким же, как и в первом примере, где применяются вложенные циклы select. Таблица 11.3 Пример содержимого представления vcustbook Edwards Smith Smith Young Edison 19991230 19991230 19991231 19991230 19990505 19990101 19990101 19990101 19991229 19990101 Использование внутренних таблиц для критериев выборки Рассмотрим дополнение for all entries команды select. Подобно вложенным циклам select, предложение where в этом примере также содержит отношение внешнего ключа. Однако циклы select не являются вложенными и результаты сразу же запоминаются во внутренних таблицах. Этот метод лучше всего проиллюстрировать на следующем примере: Чтение таблиц базы данных 135 Обратите внимание, что дополнение appending table не переопределяет содержимое внутренней таб- лицы, а добавляет новые записи в ее конец. Сравнение различных технологий программирования У каждого метода есть свои преимущества. Вложенные циклы select • Простая реализация, использующая обычный оператор select • На каждом шаге доступны все поля текущей записи таблицы. Следовательно, легко добавлять до- полнительные поля (например, bookings-connicl) • Нет неиспользуемых данных (отсутствует избыточность) • Возможны внешние соединения, даже если они не предусмотрены в СУБД. Например, можно применять тот же самый цикл select для вывода на экран имен пользователей, не зарегистриро- ванных на 01/01/1999 Представления, определенные в АВАР/4 Dictionary • При извлечении больших наборов записей таблицы данный подход обеспечивает существенно более высокую производительность, чем вложенные операторы select • Внутренняя таблица может быть использована в дальнейшем, например для сортировки записи согласно различным критериям • Некоторые таблицы представления могут содержать неиспользуемые (избыточные) данные. В при- веденном выше примере в представлении vcustbook фамилии пользователей являются избыточной информацией • Не поддерживаются внешние соединения • Добавление дополнительных полей требует изменений и инициализации представления Dictionary Оператор select выбирает все записи таблицы bookings, удовлетворяющие условию where для всех фамилий клиентов внутренней таблицы all_customers. Отношение между двумя таблицами устанавлива- ется с помощью предложения where customid = all_customers-id и дополнения for all entries. Другими словами, оператор select эквивалентен следующему фрагменту программы: 136 Глава 11 Использование внутренних таблиц и дополнения for all entries • При извлечении больших наборов записей таблицы такой подход обеспечивает существенно более высокую производительность, чем вложенные операторы select, однако уступает в скорости вы- полнения второму варианту • Упрощается добавление дополнительных полей С учетом перечисленных свойств всех трех подходов вложенные циклы select рекомендуется применять в случаях, когда: • Объем выбираемых данных не слишком велик (например, 50 записей по 200 байт каждая) • Нужно написать как можно более простую программу • Необходимо использовать внешнее соединение, например в результирующий список должны быть включены также фамилии клиентов, не зарегистрированных на 01/01/1999 • Внутренняя таблица, соответствующая представлению (второй вариант), содержит слишком много неиспользуемых данных • Список выбираемых таблиц часто меняется, однако представления в Dictionary изменяются гораздо реже С другой стороны, использование представлений, хранимых в Dictionary, дает много дополнительных преимуществ, если извлекается огромное число элементов таблиц без избыточной информации, а также если представления остаются неизменными. И, наконец, последний подход (применение for all требует разработки более сложного программного текста, но при этом обеспечивает высокую гибкость. Следует помнить, что приведенный список достоинств и недостатков не является полным. Производительность, как правило, определяется применяемой СУБД и архитектурой системы (например, скоростью передачи по сети). Обычно производительность операторов SOL можно увеличить, если использовать индексирование СУБД. Резюме • Конструкция select/endselect позволяет извлекать содержимое базы данных в режиме последова- тельного чтения записей. • Оператор select into table заполняет внутреннюю таблицу данными, выбранными из базы данных за одну операцию. • Набор отбираемых элементов можно ограничить с помощью предложения where. • Элементы, существующие в единственном экземпляре, могут считываться с помощью команды select single. При этом все поля первичного ключа должны быть заданы в предложении where как значения (операторы = или eq). • Вместо обычного считывания полных записей можно извлекать отдельные поля. • Оператор select позволяет получать статистическую информацию (например, максимальное, сред- нее или реальное число заданных записей). • Допускается сортировка результатов запроса с помощью дополнения order by или сортировки внутренней таблицы, содержащей извлеченные элементы. • Динамическая выборка поддерживается с помощью Select-Options, имен динамических таблиц и динамических предложений where. • Представления таблиц, связанных по внешнему ключу, можно считывать с помощью вложенных циклов select, определенных в Dictionary представлений или дополнения for all entries. В этой главе было рассмотрено чтение таблиц базы данных. Следующая глава посвящена способам работы с внутренними таблицами. |