Доступ к данным
В ABL есть четыре оператора, которые можно использовать для определения набора из одной или нескольких записей базы данных: FIND, FOR, REPEAT и OPEN QUERY. FIND извлекает одну запись при вызове оператора. FOR, REPEAT, и OPEN QUERY извлекают набор записей. После получения набора записей вы можете перебирать записи по одной.
В этой части мы обсудим операторы FIND, FOR, и REPEAT. С OPEN QUERY вы познакомитесь в следующей части. Здесь вы также узнаете об уникальном внутреннем идентификаторе записей ROWID.
Оператор FIND
Оператор FIND — это очень мощный способ извлечения отдельных записей из базы данных без необходимости настройки запроса или определения набора результатов. FIND извлекает одну запись из таблицы базы данных и перемещает эту запись в буфер записей.
Базовый (упрощённый) синтаксис оператора FIND:
FIND [ FIRST | LAST | NEXT | PREV ] record [ WHERE expression ]
record
Имя таблицы в базе данных.
FIRST | LAST | NEXT | PREV
Находит первую, последнюю, следующую или предыдущую запись в таблице, соответствующую заданным характеристикам.
WHERE expression
Ограничивает запрос только теми строками в таблице базы данных, которые соответствуют указанному выражению.
В следующем примере кода извлекается первая запись из таблицы Customer, имя которой начинается с «A»:
FIND FIRST Customer WHERE Customer.Name BEGINS "A". DISPLAY Customer.Name.
Дополнительные сведения см. в разделе «Доступ к данным без применения циклов: оператор FIND».
Блок FOR
Блок FOR перебирает набор связанных записей в таблице базы данных и перемещает каждую из них по очереди в буфер записей. Блок выполняет итерацию по всем записям, которые соответствуют указанным критериям, и выполняет столько итераций, сколько запрошено. Оператор FOR является очень мощным и включает в себя опции для сортировки, сопоставления и блокировки записей. Когда блок начинается, AVM оценивает выражение и извлекает первую запись, которая ему удовлетворяет. Эта запись распространяется на весь блок. Каждый раз, когда блок выполняет итерацию, AVM извлекает следующую совпадающую запись и делает её доступной для остальной части блока. Когда набор совпадающих записей исчерпан, AVM автоматически завершает блок. Вам не нужно добавлять какие-либо проверки или специальный синтаксис для выхода из блока на этом этапе. Блок FOR заканчивается оператором END.
Базовый (упрощённый) синтаксис блока FOR:
FOR [ EACH | FIRST | LAST ] record [ WHERE expression ]: /* ABL statements */ END.
EACH | FIRST | LAST
EACH, запускает итерационный блок, находя одну запись во время каждой итерации.
FIRST, находит первую запись в таблице.
LAST, находит последнюю запись в таблице.
record
Имя таблицы базы данных.
WHERE expression
Ограничивает запрос только теми строками в таблице базы данных, которые соответствуют указанному выражению.
В следующем блоке FOR EACH отображается поле Customer.Name для каждой записи в таблице Customer, где значения поля Customer.CustNum меньше 100:
FOR EACH Customer WHERE Customer.CustNum < 100 NO-LOCK: DISPLAY Customer.Name. END.
Блок REPEAT
Блок REPEAT представляет собой набор операторов, которые обрабатываются повторно, но он не считывает записи автоматически по мере выполнения итерации. Этот блок позволяет вам самостоятельно перемещаться по набору записей, а не просто автоматически переходить к следующей записи на каждой итерации. Блок REPEAT заканчивается оператором END.
Часто оператор REPEAT используется с фразой PRESELECT для выбора записей, соответствующих заданным вами критериям. PRESELECT создаёт результирующий список значений ROWID (уникальных идентификаторов), чтобы записи затем извлекались с помощью ROWID.
Обычно оператор FIND используется внутри REPEAT (PRESELECT) блока для чтения записи на каждой итерации. Есть несколько рекомендаций, которым необходимо следовать при использовании блока REPEAT:
- Используйте квалификатор NO-ERROR в FIND. Это подавляет сообщение об ошибке, которое можете получить, когда запись не найдена.
- Используйте функцию AVAILABLE для проверки наличия записи. Примените соответствующий оператор ELSE, чтобы покинуть блок (оператор LEAVE), когда нет доступной записи.
В следующем примере кода блок REPEAT используется для циклического просмотра записей о клиентах, где в качестве страны указано «USA». Когда считывается последняя совпадающая запись, оператор LEAVE выходит из блока REPEAT.
FIND FIRST Customer NO-LOCK WHERE Customer.Country = "USA". DISPLAY Customer.CustNum Customer.Name Customer.Country. REPEAT: FIND NEXT Customer WHERE Customer.Country = "USA" NO-LOCK NO-ERROR. IF AVAILABLE Customer THEN DISPLAY Customer.CustNum Customer.Name Customer.PostalCode. ELSE LEAVE. END.
ROWID
Каждая запись базы данных имеет уникальный внутренний идентификатор, известный как ROWID. Этот идентификатор имеет тип данных ROWID. Для получения ROWID записи базы данных, которая в данный момент находится в буфере записей, используется функция ROWID.
В следующем примере показано использование функции ROWID для получения идентификатора записи, которая в данный момент находится в буфере. Позже идентификатор используется для повторной выборки записи с блокировкой, чтобы её можно было изменить.
VAR ROWID custrid. FIND FIRST Customer NO-LOCK. custrid = ROWID(Customer). // Get the rowid and save it, so it can be refetched. IF Customer.balance > 0 THEN DO: FIND Customer WHERE ROWID(Customer) = custrid EXCLUSIVE-LOCK. Customer.Comments = "Balance remaining". // Update the Comments field in the Customer record DISPLAY Customer.Name Customer.Balance Customer.Comments FORMAT "X(20)". RELEASE Customer. END.