|
При отсутствии границ и условий сканируется вся база данных. Команда SCAN является исключительно удобным средством перемещения в базе.
SCAN-цикл может быть завершен как по достижении <границ> его действия, так и при встрече конца базы данных. Выяснить это обстоятельство можно с помощью функции EOF(). Если EOF()=.t., цикл завершен раньше времени. Исключение составляет цикл с FOR-условием - такой цикл всегда продолжается до достижения конца файла.
• Здесь уместно обсудить вопрос о технике перемещения в базе данных "по условию". Ниже приводятся фрагменты программ поиска в базе KADR.DBF всех записей с фамилиями, начинающимися с буквы "П", как с использованием цикла DO WHILE, так и SCAN-цикла. Рассматривается как последовательный поиск, так и ускоренный с применением индексного файла KADRFAM.IDX, созданного по полю FAM.
1. USE kadr
2. USE kadr [INDEX kadrfam] LOCATE FOR fani='n' SCAM FOR fairF='n' DO WHILE!EOF() <обработка записи>
ENDSCAN
CONTINUE ENDDO
3. USE kadr INDEX kadrfam
4. USE kadr INDEX kadrfam SEEK 'П' SEEK 'П' DO WHILE fanr='n' SCAN WHILE fam='n'
<обработка ааписи> <обработка эаписи>
SKIP
ENDSCAN
ENDDO
В примере 2 подключение индекса (опция INDEX kadrfam) обеспечивает сканирование базы с оптимизацией по технологии Rushmore. В этом случае пример идентичен примеру 4. Однако для
оптимизирующей технологии лучше, если главный индекс не назначен (ORDER 0). Тогда сканирование будет выполнятся процентов на 20-25 быстрее. В этом случае, однако, записи будут предъявляться в естественном порядке.
Очевидно, что использование SCAN-цикла существенно удобнее. Однако это не исключает ситуации, когда имеет смысл применение для указанных целей и цикла DO WHILE, в особенности если нам нужно самим управлять перемещением указателя записей.
Такая ситуация может возникнуть, например, при необходимости сканировать базу в обратном направлении - снизу-вверх:
DO WHILE!BOF()
<обрабоччса ааписи>
SKIP -1 ENDDO
Следует заметить, что выполнение каждой команды ENDSCAN перемещает указатель записей. Это значит, что завершение SCAN-цикла с WHILE-условием переносит нас за пределы действия этого условия.
Пусть нам нужно найти и вывести суммарную зарплату S для каждого подразделения базы KADR.DBF (KADRPODR.IDX - индексный файл по полю PODR). Использование двух вложенных SCAN-циклов (ниже слева) повлечет ошибку - пропуск одной записи для каждого нового подразделения. Ниже справа приведено правильное решение.
USE kadr INDEX kadrpodr USE kadr INDEX kadrpodr SCAN DO WHILE!EOF() p=podr p=podr
8=0 S=0
SCAN WHILE podr=p SCAN WHILE podr=p
s=3+szar s=s+szar ENDSCAN ENDSCAN?podr,s?podr,s ENDSCAN ENDDO
Аналогично выполняется построение циклов сканирования для организации обработки данных с любой глубиной их группировки. Важно только, чтобы они были упорядочены-соответствующим образом.
Для иллюстрации техники группировки данных нам понадобится другая база данных. Положим она содержит сведения о работниках предприятия (RAB.DBF) с указанием их принадлежности подразделению (поле PODR), бригаде (BRIG) и звену (ZVENO), а также фамилию (FAM) и другие личные данные, которые сейчас не существенны. База имеет следующую структуру:
Field # Field Name Type Width
1 PODR Character 10
2 BRIG Character 2
3 ZVENO Character 2
4 FAM Character 26
5...
Нашей целью является вывод списка всех сотрудников предприятия с разбивкой по подразделениям, бригадам и звеньям, а также подсчет числа приписанных к ним работников, т.е. осуществление трех уровней группировки.
С тем, чтобы решение задачи было возможно, база проиндексирована по перечисленным полям командой
INDEX ON podr+brig+zveno TO rab
Текст программы приведен ниже.
*-1ТОБ.РКС-----------------------итоговая сводка работников
USE rab INDEX rab
CLEAR
? 'Список работников с разбивкой по местам работы'
•••а=0 66 общее число работников предприятия DO WHILE 'EOF() 66 внешний цикл
ass=G 66 число работников подразделения p=podr 66 название подразделения? 'ПОДРАЗДЕЛЕНИЕ',?
DO WHILE p=podr 66 цикл по подразделению ss=0 66 число работников бригады b=brig 66 номер бригады?' БРИГАДА НОМЕР',Ь DO WHILE p=podr AND b=brig 66 цикл по бригаде
8=0 66 число работников звена z=zveno 66 номер звена? ' ЗВЕНО НОМЕР', z 66 цикл по звену SCAN WHILE p=podr AND b=brig AND z=zveno
?? fam AT(10) 66 фамилии работников 8=8+1 66 подсчет работников ENDSCAN
? ' ',LTRIM(STR(s)),'чел.' 66 работников в звене эа=зэ+з ENDDO
? ' В бригаде',b,LTRIM(STR(8s)),'чел. ' 66' в бригаде sss=sss+ss
ENDDO? ' В подразделении',p,LTRIM(STR(sss)),'чел.' && подразд.
SSSS=3SSS+SSS
ENDDO
? 'ВСЕГО',LTRIM(STR(aass)),'человек' && на предприятии
RETURN &&—--——————--——------———-———----—----———
Видим, что для наших целей понадобилось организовать четыре цикла, из которых только самый внутренний SCAN-цикл осуществляет перемещение указателя записей. Остальные WHILE-ЦИКЛЫ контролируют заданные условия, инициализируют, формируют и выводят значения сумм.
Дата добавления: 2015-04-26; просмотров: 39 | Поможем написать вашу работу | Нарушение авторских прав |
<== предыдущая лекция | | | следующая лекция ==> |
Цикл сканирования БД | | | Тема 3. Управляющие конструкции языка ТП |