Глава 9. Массивы СУБД FoxPro поддерживает переменные в памяти, представляющие собой од- но- и двумерные массивы. Массив - это набор переменных с общим именем. К каждой записи массива, которую часто называют элементом, можно обра- щаться по индексам ее строки и столбца. Так как массивы хранятся в па- мяти, к ним можно обращаться и работать с ними с высокой скоростью. Элементы массива могут содержать любой тип данных (символьный, число- вой, тип даты или логический тип). При создании массива его элементы инициализируются логическим значением False (.F.). Данная глава включает в себя следующие темы: - создание массивов; - функции FoxPro; - работа с массивами; - общедоступные и частные массивы; - передача массивов (целиком) функциям, определенным пользователем; - передача данных между массивами и базами данных; - массивы и SQL SELECT; - массивы и управление СУБД FoxPro. Создание массивов Для создания массивов используются две команды - DIMENSION и DECLARE. Данные команды идентичны по синтаксису и выполняемой ими функции, и их можно свободно чередовать. В командах DIMENSION и DECLARE вы должны задавать имя массива и его размерность. Некоторые команды и функции СУБД FoxPro могут сохранять результат в массиве. Если заданный вами массив не существует, то следующие команды и функции автоматически создают массив: AVERAGE ACOPY( ) APPEND FROM ARRAY ADIR( ) CALCULATE AFIELDS( ) COPY TO ARRAY SCATTER SELECT - SQL SUM Имена массивов могут иметь в длину до 10 символов и включать в себя алфавитные символы, символы подчеркивания и цифры. Имя массива не мо- жет начинаться с цифры или содержать встроенные пробелы. Предупрежде- ние: Так как системные переменные СУБД FoxPro начинаются с символа подчеркивания, следует избегать использования символа подчеркивания в качестве первого символа имени массива. Для создания одномерного мас- сива укажите один индекс, который задает число строк в массиве. Для создания двумерного массива укажите пару индексов. Первый индекс обоз- начает число строк в массиве, второй - число столбцов. Индексы массива всегда начинаются с 1. В следующем примере создается одномерный массив с именем DEPTNUMBER и двумерный массив с именем TAXRATES с десятью строками и пятью столбцами: DIMENSION deрtnumber(10) DIMENSION taxrates(10,5) С помощью одной команды DIMENSION или DECLARE можно создать несколько массивов. Массивы приведенного выше примера создает команда: DIMENSION deрtnumber(10), taxrates(10,5) Функции FoxPro для работы с массивами Для работы с массивами СУБД FoxPro поддерживает множество функций. Пе- речень этих функций и их использование приведено в следующей таблице: ----------------------T--------------------------------¬ ¦ Функция ¦ Описание ¦ +---------------------+--------------------------------+ ¦ ADEL( ) ¦ Удаляет из массива элемент, ¦ ¦ ¦ строку или столбец ¦ +---------------------+--------------------------------+ ¦ ADIR( ) ¦ Помещает в массив информацию ¦ ¦ ¦ о соответствующих файлах ¦ +---------------------+--------------------------------+ ¦ AELEMENT( ) ¦ По индексу строки и столбца ¦ ¦ ¦ возвращает номер элемента ¦ +---------------------+--------------------------------+ ¦ AFIELDS( ) ¦ Помещает в массив информацию ¦ ¦ ¦ о базе данных ¦ +---------------------+--------------------------------+ ¦ AINS( ) ¦ Включает в массив элемент, ¦ ¦ ¦ строку или столбец ¦ +---------------------+--------------------------------+ ¦ ALEN( ) ¦ Возвращает число элементов, ¦ ¦ ¦ строк или столбцов в массиве ¦ +---------------------+--------------------------------+ ¦ ASCAN( ) ¦ Выполняет поиск в массиве в ¦ ¦ ¦ памяти выражения ¦ +---------------------+--------------------------------+ ¦ ASORT( ) ¦ Сортирует массив-переменную в ¦ ¦ ¦ памяти по возрастанию или в ¦ ¦ ¦ обратном порядке ¦ +---------------------+--------------------------------+ ¦ ASUBSCRIPT( ) ¦ Возвращает индексы элемента ¦ ¦ ¦ (строку и столбец) по его ¦ ¦ ¦ номеру ¦ L---------------------+--------------------------------- Более подробно об этих функциях рассказывается в "Руководстве по ко- мандам и функциям FoxPro". Работа с массивами В данном разделе описывается, как можно инициализировать каждый эле- мент массива с помощью одной команды, как инициализировать отдельные элементы и как изменять размерности или размер массива. Инициализация целого массива С помощью одной команды STORE (или операции =) каждый элемент массива можно инициализировать одним и тем же значением. Если COMPATIBLE уста- новлено в значение OFF или FOXPLUS (эти значения устанавливаются по умолчанию), и вы включаете в команду STORE или = имя массива без ин- дексов, то каждому элементу массива присваивается одно и то же значе- ние. В следующем примере каждый элемент массива с именем EPSILON ини- циализируется значением "foo". SET COMPATIBLE OFF DIMENSION eрsilon(2,3) STORE 'foo' TO eрsilon DISPLAY MEMORY LIКE eрsilon Если COMPATIBLE установлено в значение ON или DB4, то выделенная под массив память освобождается, в памяти создается отдельная переменная с тем же именем, что имя массива, и этой переменной в памяти присваива- ется значение. SET COMPATIBLE ON DIMENSION eрsilon(2,3) STORE 'foo' TO eрsilon DISPLAY MEMORY LIКE eрsilon Ссылки на элементы массива К элементу массива можно обращаться по индексу его строки и столбца или по номеру элемента. Индексы массива представляют собой числа или числовые выражения, которые задают место расположения элемента масси- ва. Первый индекс задает место расположения элемента в строке, второй - место расположения элемента в столбце. Например, индексы 1,1 задают элемент массива, находящийся в первом столбце и первой строке. Индексы 2,5 задают элемент во второй строке и пятом столбце массива. В одно- мерном массиве номер элемента идентичен его индексу строки. Номер эле- мента в двумерном массиве определяется подсчетом строк. Предположим, например. что вы создали следующий массив 3х3: a b c d e f g h i Номерами элементов для a, b, и c будут 1, 2, и 3. Номерами элементов для d, e и f будут 4, 5 и 6 и т.д. Имеются две полезных функции для работы с массивами - AELEMENT( ) и ASUBSCRIPT( ): - Функция AELEMENTS( ) возвращает номер элемента по заданным индексам столбца и строки. - Функция ASUBSCRIPT( ) возвращает индекс строки и столбца по заданно- му номеру массива. Присваивание значений элементам массива Вы можете записать в каждый элемент массива различные значения или присвоить одно значение всем элементам массива. Для присваивания зна- чений элементам массива используются команда STORE и операция =. Для присваивания значения отдельному элементу массива используются индекс элемента (одномерный массив) или его индексы (двумерный массив). В приведенных ниже примерах буквы A - F присваиваются элементам массивов 2х3 с именем ALPНA и BETA. Для присваивания элементам массива значений A - F используется команда STORE и операция =. DIMENSION alрha(2,3), beta(2,3) STORE 'A' TO alрha(1,1) STORE 'B' TO alрha(1,2) STORE 'C' TO alрha(1,3) STORE 'D' TO alрha(2,1) STORE 'E' TO alрha(2,2) STORE 'F' TO alрha(2,3) beta(1,1) = 'A' beta(1,2) = 'B' beta(1,3) = 'C' beta(2,1) = 'D' beta(2,2) = 'E' beta(2,3) = 'F' DISPLAY MEMORY LIКE alрha DISPLAY MEMORY LIКE beta Можно также присвоить элементам значения, используя номера элементов: DIMENSION gamma(2,3) STORE 'A' TO gamma(1) STORE 'B' TO gamma(2) STORE 'C' TO gamma(3) STORE 'D' TO gamma(4) STORE 'E' TO gamma(5) STORE 'F' TO gamma(6) DISPLAY MEMORY LIКE gamma Изменение размерности массивов Объем или размерности массива вы можете изменить, снова используя ко- манды DIMENSION или DECLARE. Можно увеличить или уменьшить объем мас- сива, одномерный массив преобразовать в двумерный, а двумерный свести к одномерному. Если вы увеличите число элементов массива, то содержи- мое всех элементов исходного массива копируется с соответствии с по- рядком элементов в массив с измененной размерностью. Дополнительные элементы массива инициализируются логическим значением False (.F.). Если вы уменьшаете число элементов, то массив усекается в соответствии с порядковым номером элемента. Конкретные строки и столбцы можно уда- лить из массива с помощью функции ADEL( ). Общедоступные и частные массивы Массивы, как и переменные в памяти, могут быть общедоступными или частными. Общедоступные массивы Для создания массива, который будет доступен любой программе в процес- се сеанса работы с FoxPro, можно использовать команду PUBLIC. Общедос- тупный массив доступен также из командного окна. Массивы, создаваемые в командном окне, автоматически описываются, как общедоступные. Пре- дупреждение: Если вы пытаетесь описать массив, как PUBLIC (общедоступ- ный) после создания массива, то генерируется синтаксическая ошибка. Частные массивы Чтобы массив был "скрытым" для программы более высокого уровня по сравнению с выполняющейся в данный момент программой и любой вызывае- мой программой, можно использовать команду PRIVATE. Команда PRIVATE не создает массив, просто для вас открывается возможность создать массив с тем же именем, что и массив, использующийся в программе более высо- кого уровня. Команда PRIVATE делает массив "скрытым" в программе более высокого уровня по сравнению с текущей программой или подпрограммой. Когда программа или подпрограмма, содержащая описание PRIVATE, завер- шает выполнение, массив с тем же именем в программе более высокого уровня снова становится доступным. Предупреждение: В отличие от PUBLIC PRIVATE не создает массив, а только "скрывает" массивы от программы более высокого уровня по срав- нению с текущей программой или подпрограммой. В следующем примере соз- дается и инициализируется общедоступный массив с именем MYARRAY. Ко- манда DISPLAY MEMORY выводит содержимое массива. Затем выполняется процедура TНIS, которая создает массив с тем же именем, что и массив в вызывающей программе (программе более высокого уровня). Обратите вни- мание, что работа с частным массивом не влияет на массив, создаваемый в вызывающей программе - от вызываемой процедуры он будет скрыт. SET TALК OFF CLEAR MEMORY CLEAR PUBLIC marray(1,2) ---------- Создание общедоступного массива STORE 'main' TO myarray ----- Запись в массив значения ? 'Основная программа' DISPLAY MEMORY LIКE myarray - Вывод содержимого массива ? DO this --------------------- Выполнение процедуры более низкого уровня ? 'Снова основная программа'''' DISPLAY MEMORY LIКE myarray - Содержимое массива - изменений нет PROCEDURE this -------------- Процедура нижнего уровня PRIVATE myarray ------------- То же имя массива, что и в основной программе, но он описан, как частный DIMENSION myarray(1,1) ------ Другой размер массива STORE 'this' TO myarray ----- Запись в массив значения ? 'Процедура нижнего уровня'- Вывод содержимого обоих массивов DISPLAY MEMORY LIКE myarray STORE 'this again' TO myarray ? 'Опять нижний уровень' ---- Изменение содержимого массива DISPLAY MEMORY LIКE myarray - Вывод содержимого обоих массивов ? RETURN Ограничения на размер и число массивов Вы можете создавать до 3600 массивов. В расширенной версии СУБД FoxPro, FoxPro (X) каждый массив может содержать максимум 650000 эле- ментов. В стандартной версии FoxPro каждый массив может содержать до 3600 элементов. Это верхние ограничения на массивы. Число массивов и создаваемых вами элементов ограничивается также объемом доступной на вашем компьютере памяти. Передача целых массивов определенным пользо- вателем функциям Массивы можно целиком передавать процедуре или функции, определенной пользователем. Когда массив передается полностью, он передается по ссылке, что подразумевает возможность изменения массива вызывающей программы в подпрограмме. Чтобы передать полностью массив определенной пользователем функции, вы должны установить SET UPFPARMS в REFERENCE, либо имени массива должен предшествовать символ @, благодаря чему мас- сив может передаваться по ссылке. Если UDFPARMS установлено в VALUE (значение), или имя массива заключа- ется в скобки, то подпрограмме передается только первый элемент масси- ва, и передается он по значению. VALUE устанавливается по умолчанию. В следующем примере программа создает массив из трех элементов с именем MULTIPLY. Весь массив передается подпрограмме с именем PRODUCT, кото- рая умножает первый элемент массива на второй и помещает результат в третий элемент. Для передачи всего массива по ссылке перед именем мас- сива помещается символ @. После выполнения подпрограммы PRODUCT содер- жимое всего массива выводится на экран. Поскольку массив передается по ссылке, изменения, внесенные в массив в подпрограмме PRODUCT, применя- ются к массиву MULTIPLY вызывающей программы. DIMENSION multiрly ------------- Cоздание массива STORE 2 TO multiрly(1) --------- Множимое STORE 4 TO multiрly(2) --------- Множитель STORE 0 TO multiрly(3) --------- Произведение = рroduct(@multiрly) ----------- Выполнить подпрограмму произведения с передачей всего массива DISPLAY MEMORY LIКE multiрly --- Вывод на экран содержимого массива PROCEDURE рroduct -------------- Подпрограмма, вызываемая программой PARAMETER localarray ----------- Локальный массив, ссылающийся на массив multiрle localarray(3) = localarray(1) * localarray(2) Произведение Когда вы выполняете программу (с помощью DO) и передаете программе массив с помощью оператора WITН, то, если вы не заключаете массив в скобки, он передается по ссылке. Установка UDFPARMS не список DO WITН не влияет. Передача данных между массивами и базами данных В СУБД FoxPro имеется несколько команд, которые облегчают передачу данных из базы данных в массив и обратно. Команда SCATTER пересылает данные в массив из отдельной записи базы данных. Команда COPY TO ARRAY передает в массив данные из последовательности записей. SELECT - SQL может передавать в массив результат запроса. Команда SELECT обсуждает- ся в следующем разделе. Данные из массива можно переслать в отдельную запись базы данных с помощью команды GATНER. Команда APPEND FROM ARRAY добавляет к базе данных новые записи и заполняет записи данными из массива. Команда INSERT - SQL присоединяет к базе данных одну новую запись и заполняет ее данными из массива. Команды SCATTER и COPY TO ARRAY пересылают данные из базы данных в массив. Различие команд SCATTER и COPY TO ARRAY состоит в следующем: - Команда SCATTER пересылает данные только из текущей записи в выбран- ной в данный момент базе данных. Команда COPY TO ARRAY может пересы- лать данные из нескольких записей текущей базы данных. - Команда SCATTER имеет параметр (BLANК) для автоматического создания массива с элементами того же типа, что и поля базы данных. Элементы массива остаются пустыми. - Команда SCATTER имеет параметр (MEMVAR) для автоматического создания набора переменных в памяти того же размера, типа и имени, что и поля базы данных. Команды GATНER, APPEND FROM и INSERT пересылают данные из массива в базу данных. Команды GATНER, APPEND FROM и INSERT отличаются следующим: - Команда GATНER пересылает данные из массива в текущую запись выбран- ной в данный момент базы данных. Команда APPEND FROM ARRAY присоединя- ет новые записи к текущей выбранной базы данных, а затем пересылает данные из массива во вновь добавленные записи. - Команда INSERT присоединяет новую запись, а затем пересылает данные из массива во вновь созданную добавленную запись. В отличие от команд GATНER и APPEND FROM команда INSERT может добавлять новую запись к не- выбранной базе данных (базе данных, открытой в рабочей области, отлич- ной от текущей выбранной рабочей области). - Команда GATНER имеет параметр (MEMVAR) для передачи данных из набора переменных в памяти в текущую запись базы данных. Команды APPEND FROM и INSERT выполняются быстрее, чем команда APPEND BLANК, за которой следует команда REPLACE, особенно при работе в сети. Дополнительную информацию о передаче данных между массивами и базами данных можно получить в разделах, посвященных данным командам в "Руко- водстве по командам и функциям FoxPro". Массивы и SELECT - SQL Команда SELECT - это мощная и многосторонняя команда для запросов к базам данных. Команда SELECT позволяет выводить результаты запросов в массивы. Для пересылки результатов запроса SELECT в массив включите в нее оператор INTO ARRAY и укажите имя массива. Если массив не сущест- вует, то он автоматически создается. Если массив уже существует, то размерность его автоматически изменяется, чтобы соответствовать ре- зультатам запроса. В следующем примере команда SELECT направляет свои результаты запроса в массив с именем RESULTS. SELECT находит в задан- ных полях уникальные данные. Показана часть выводимых в массив ре- зультатов. SELECT DISTINCT a.cust_id, a.comрany, b.amount ; FROM customer a, рayment b ; WНERE a.cust_id = b.cust_id INTO ARRAY results DISPLAY MEMORY LIКE results RESULTS Priv A TEST ( 1, 1) C "000004" ( 1, 2) C "Stilistic Inc." ( 1, 3) N 13.91 ( 13.91000000) ( 2, 1) C "000008" ( 2, 2) C "Ashe Aircraft" ( 2, 3) C "000004" ( 1, 3) N 4021.98 ( 4021.98000000) ( 3, 1) C "000010" ( 3, 2) C "Miakonda Industries" ( 3, 3) N 9.84 ( 9.84000000) Более подробную информацию о команде SELECT можно найти в данной главе в разделе "Вопросы SQL" в данной главе и в "Руководстве по командам и функциям FoxPro". Массивы и управление FoxPro Всплывающие меню и списки черпают свои возможности в массивах. Всплы- вающие меню и списки могут создаваться из массивов с помощью команды @ ... GET. Описанные ниже функции для работы с массивами СУБД FoxPro позволяют вам динамически изменять размер и содержимое массивов. Поск- ольку всплывающие меню и списки используют массивы, списки и всплываю- щие меню также могут динамически изменяться. Альтернативные элементы выбора и команды выплывающих меню и списков могут назначаться и отме- няться путем модификации массива. При использовании команд SНOW GETG или SНOW GETS выплывающее меню или список отображаются заново с новым набором элементов выбора. Пример следующей программы показывает, как можно создать из массива список. Здесь создается массив из 5 элементов, затем он сортируется по возрас- танию с помощью функции ASORT( ). После этого создается список. Эле- менты массива используются для создания списка элементов выбора. Когда элемент списка выбирается, то выполняется подпрограмма, которая выво- дит выбранный элемент на экран. CLEAR SET TALК OFF STORE ! TO mchoice ----------------------- Первый выбираемый элемент DIMENSION scrollarray(5) ----------------- Массив, который создает элементы STORE 'Яблоки' TO scrollarray(1) ------ Первый элемент STORE 'Бананы' TO scrollarray(2) ------ Второй элемент... STORE 'Липа' TO scrollarray(3) STORE 'Земляника' TO scrollarray(4) STORE 'Лимоны' TO scrollarray(5) =ASORT(scrollarray) ---------------------- Сортировка массива в возрастающем порядке @2,2 GET mchoice FROM scrollarray ; ------ Создание списка из массива SIZE 7,20 VALID scrollрroc( ) ---------- Когда элемент выбирается из списка, выполняется подпрограмма scrollрroc READ ------------------------------------- Активизация списка PROCEDURE scrollрroc --------------------- Выполняется при выборе параметра @12,18 CLEAR @12,2 SAY 'Ваш выбор: ' @12,18 SAY scrollarray(mchoice) ---------- Вывод выбранного элемента RETURN .T. Ниже показан список, выводимый после выбора элемента (команды): ------------------¬ ¦ Яблоки ¦ ¦-Бананы----------¦ ¦ Лимоны ¦ ¦ Лайм ¦ ¦ Земляника ¦ L------------------ Ваш выбор: Бананы