FOR_EACH - IN - DO - END


Синтаксис

FOR_EACH Item [ IN Set ] DO [ [ ForEachAttributes ] ]
 (* тело цикла *)
END
ForEachAttributes = ForEachAttributeName ( ForEachAttributeValues )
                { , ForEachAttributeName ( ForEachAttributeValues ) }
ForEachAttributeName = START | STOP

Описание

Оператор цикла FOR_EACH существует в двух вариантах.

Первый вариант - фраза IN Set присутствует.

  1. Перебор элементов коллекции Set. Для этого автоматически заводится скрытый перечислитель коллекции аналогично тому, как это делает функция CreateENUMERATOR. На каждой итерации цикла приемнику Item присваивается очередной элемент коллекции, а значит Item должен быть совместим со всеми ними по присваиванию, после чего выполняется тело цикла. Порядок перебора коллекции как правило не определен; гарантируется лишь, что все ее элементы будут перебраны. Но для некоторых коллекций порядок перебора явно декларируется в описании.
  2. Перебор элементов массива Set. На каждой итерации цикла приемнику Item присваивается очередной элемент массива, после чего выполняется тело цикла. Перебор начинается с нулевого элемента и завершается на первом же пустом элементе.

Второй вариант - фраза IN Set отсутствует.

  1. Перебор допустимых значений скаляра. Выполняется от минимального значения до максимального, приемник Item должен иметь скалярный тип. На каждой итерации цикла приемнику Item присваивается очередное значение, после чего выполняется тело цикла.
  2. Перебор записей текущего селекта таблицы БД. Выполняется быстрее, чем процедурами NEXT и PREV, за счет пакетной передачи записей с сервера. Возможность появилась в версии 14.254.050. В качестве Item ожидается имя регулярной или нерегулярной таблицы БД. Нерегулярная таблица должна быть заранее подключена процедурой ATTACH_TABLE, иначе исключение 119. Селект в таблице Item к началу FOR_EACH должен быть определен, иначе исключение 363, рекомендуется это делать вызовом SETSEL. На каждой итерации цикла курсор по умолчанию таблицы Item позиционируется на очередную запись селекта, после чего выполняется тело цикла. Допускаются вложенные FOR_EACH, в том числе и с тем же значением Item, а также любая их комбинация с процедурами позиционирования. Если в теле цикла был изменен селект курсора Item, он восстановится в начале следующей итерации. Экземпляры записей соответствуют тому режиму доступа, который был таблице Item в момент входа в FOR_EACH, и в начале каждой итерации в таблице Item должен быть именно этот режим, иначе исключение 978. Полученные записи блокируются в соответствии с режимом доступа, поэтому возможен конфликт блокировок. FOR_EACH не учитывает выполненные модификации, причем не только чужих транзакций, но и своей собственной. Поэтому REPLACE записи, полученной непосредственно из FOR_EACH может выбросить исключение 385, что означает, что предварительно следовало выполнить GETLASTVERSION.
    В данном применении FOR_EACH (начиная с V14.267.060) возможно указание ForEachAttributes с целью ограничения выборки записей селекта и определения направления прохода. Атрибут START описывает запись селекта, с которой нужно начинать, STOP - запись, которой нужно заканчивать (включительно). Аргументы обоих атрибутов:
    1. GE или GT - определение левой (с меньшим значением) границы интервала внутри селекта; LE или LT - правой (с большим значением). Через запятую можно указать значения полей, незафиксированных в селекте, по аналогии с SRCINSEL. Если значения полей не указаны, граница интервала совпадает с соответствующей границей селекта
    2. CURRENT - границей интервала является текущая позиция, которая обязана быть определена, иначе исключение 930.
    Направление прохода: от START в сторону STOP. Т.о. если аргумент START - это GE или GT, то проход вперед, т.е. записи просматриваются в сторону возрастания, если LE или LT - проход назад. STOP должен иметь противоположную границу по сравнению со
    START, иначе исключение 978. Аргумент CURRENT не уточняет правая это граница или левая, поэтому направление определяет другая граница интервала, а если она явно не объявлена, то исключение 978. Но допускается одновременно [START(CURRENT), STOP(CURRENT)] - обрабатывается единственная запись.
    Если атрибуты не указаны, то проход вперед от первой записи селекта к последней.
    Примеры:
    1. [START(GE, Field_5_Value_1), STOP(LE, Field_5_Value_2, Field_6_Value_1)] - вперед от первой записи с Field_5_Value_1 до последней с Field_5_Value_2 И Field_6_Value_1
    2. [START(LT, Field_Value_1), STOP(GE, Field_Value_2)] назад от последней из записей со значениями меньшими Field_Value_1 до первой с Field_Value_2
    3. [START(GE, FieldValue)] - вперед от первой записи с FieldValue до конца селекта
    4. [START(LE), STOP(GE)], [STOP(GE)], [START(LE)] - назад все записи селекта
    5. [START(CURRENT), STOP(GE)] - от текущей позиции назад до начала селекта
    6. [START(CURRENT), STOP(LE)] - от текущей позиции вперед до конца селекта
    7. [START(CURRENT), STOP(CURRENT)] - единственная текущая запись
    8. [START(CURRENT)], [STOP(CURRENT)], [START(GE ...), STOP(GE ...)], [START(LE ...), STOP(LT ...)] и т.п. - исключение 978 "невозможно определить направление"

Во всех вариантах для досрочного выхода из цикла может быть использован оператор EXIT.