©Большаков Сергей Алексеевич, к.т.н., доц.,
технический консультант Interface Ltd.
©2002
Рис. 1 Заполнение таблицы в режиме TBL_FillNormal и TBL_FillAll функцией SqlFetchRow
В случае режима TBL_FillAll курсор может быть закрыт и после выполнения функции SalTblPopulate, так как выборка будет полностью завершена. Этого нельзя делать в режиме TBL_FillNormal, освобождение курсора необходимо сделать при обработку сообщения обработки строки. Отметим, что после формирования строки будет инициировано сообщение SAM_FetchRowDone, тоже для каждой строки.
Рис. 2 Закрытие курсора в режиме TBL_FillAll
Выборка в режиме TBL_FillNormal, выполняется аналогично, только в этом случае закрывать курсор можно только после чтения всех записей, а оно завершиться после просмотра в таблице всех выбранных записей. Если записи не просматриваются пользователем до конца, то закрытие курсора нужно выполнить перед следующей выборкой в таблицу или при необходимости его другого применения. Запрос на выборку в режиме TBL_FillNormal, показан на рисунке ниже.
Примечание: В этом случае лучше иметь отдельный курсор для каждого применения, иначе возможны проблемы доступа: выборка (а она определяется курсором) будет разрушена и любая попытка скроллинга таблицы будет невозможна.
Рис. 3 Выборка в таблицу в режиме TBL_FillNormal
При выборке в режиме фона (TBL_FillAllBackground) курсор можно закрывать, только по завершению всей выборки. Запрос в этом режиме показан ниже.
Рис. 4 Выборка в таблицу в режиме TBL_FillAllBackground
Для этого случая предусмотрено специальное сообщение SAM_FetchDone, которое формируется при завершении процесса фоновой выборки. На рисунке, приведенном ниже, показана процедура обработки этого сообщения, с индикацией типа сообщения и закрытием курсора выборки.
Рис. 5 Обработка сообщения SAM_FetchDone и закрытие курсора
После выполнения выборки мы получим окно представленное ниже на рисунке. Первая колонка заполнена номерами записей. В данном примере для второй записи произведена замена содержимого колонки "Имя". Это имя совпало с фамилией для замены – "Иванов".
Рис. 6 Окно приложения с заменой фамилии
Алгоритм замены заложен в обработку сообщения SAM_FetchRowDone, так как при этой операции поля таблицы уже не будут изменяться и они сформированы. При совпадении фамилии (colName = dfFamReplace) значение в колонке будет заменено на "***".
Рис. 7 Обработка сообщения SAM_FetchRowDone
Для демонстрации различных режимов заполнения таблицы рекомендуем Вам использование отладчика (поставьте в процедурах обработки сообщений таблицы точки останова) и обращайте внимание на индикатор сообщений. Кроме того, при анализе приложения можете использовать окно сообщений отладчика и окно просмотра переменных.
Чтобы не усложнять интерфейс при анализе разных режимов используйте способ
комментирования и разкомментирования запросов в процедуре обработки нажатия
клавиши ("Добавить из БД" - pbAddToTabl)
После выполнения действий вы получите работающее приложение. Некоторые детали
мы сознательно опустили из данного изложения, так как они подробно были рассмотрены
ниже. Приложение, которое вы получите ( step61.app), можно
скачать здесь ( для редактора и дизайнера: здесь нужно обеспечить скачивание
файла step61.app,
который поставляется вместе со статьей)
Далее рассмотрим работу с БД на основе выборки. Возможны два варианта: работа с таблицей и работа непосредственно с выборкой из БД (Result Set). Ниже приведено окно приложения, которые мы построили для изучения этих режимов. В процессе дальнейшего изучения данной статьи Вы самостоятельно, тоже сможете построить такое приложение. Заполнение данного окна предназначено для изучения режима совместной работы таблицы и выборки. Отметим, что задача разбивается на следующие шаги:
Рис. 8 Окно приложения для изучения операций работы с записями в режиме таблицы.
Для переключения режимов предусмотрены специальные радиокнопки ("Таблица" и "Result
Set"), расположенные в нижней части окна. Верхняя часть окна у нас такая
же, как и в предыдущем приложении. Поэтому оставим ее без комментария. В нижней
части окна поля имеют следующее назначение: поле "Номер записи" указывает
на текущую запись, поле "Имя" используется для ввода и чтения имени
сотрудника, поле "Оклад" – для ввода/вывода оклада, а список "Должность",
для индикации и ввода должностей. Защищенное поле "Размер RS" – определяет
объем выборки из БД.
Кнопки для работы с записями имеет следующее назначение: кнопка "Добавить" добавляет
записи, кнопка "Удалить" используется для их удаления, а кнопка "Изменить" предназначена
для модификации записей. Думаю, что навигационные кнопки понятны всем по смыслу: "в
начало выборки", "назад на запись", "вперед
на запись" и "в
конец выборки". Поле "Номер для выбора" и кнопка "Выбрать
по номеру" позволяют установить текущим конкретный номер записи из таблицы
или выборки. Специальная кнопка "Сформировать RS" (выборку), доступна
только в режиме "Result Set".
На следующем рисунке показаны все объекты данного приложения. По смыслу и названию читателю несложно будет их сопоставить с экранными элементами, поэтому не будем тратить время на это описание. Отмечу только, что в таблице для синхронизации доступа у нас появилась специальная скрытая колонка с названием colROWID, она будет нами использоваться для редактирования и удаления записей.
Рис. 9 Описание объектов окна приложения
Рассмотрим теперь цикл формирования записей в таблицу на нижнем уровне. Первоначально выполняется запрос, знакомый нам по другим примерам. Он выполняется с помощью функции выполняющей одновременно компиляцию и формирование выборки – SqlPrepareAndExecute. В принципе эта операция может быть разделена на две: отдельно компиляция (SqlPrepare) и отдельно формирование выборки (SqlExecute). В данной функции указываются два параметра: курсор (hSql2) и текст запроса. В самом тексте запроса в разделе оператора выборки INTO перечислены связующие переменные (bind variables), которые для нашего примера совпадают с колонками таблицы: tblTest.colName, tblTest.colOklad, tblTest.colDolg, tblTest.colROWID. Для выделения связующих переменных перед ними ставиться двоеточие. Отметим в этом запросе наличие выборки ROWID в специальную скрытую колонку.
Примечание: В БД для любой записи SQLBase автоматически хранит специальное уникальное полу имеющее имя ROWID. Это символьное поле (40 символов), которое генерируется по специальным правилам и служит для идентификации записей. При изменении и удалении записей оно изменяет свое значение, поэтому оно может служить для выяснения того, была ли запись изменена или удалена. В нашем примере для операций изменения и удаления записей, мы будем использовать эту колонку.
Правильность выполнения операций можно проверить по коду возврата функции (в нашем примере это опущено). После выполнения запроса на выборку мы определяем ее размер с помощью функции SqlGetResultSetCount. Если выборка ненулевая (nCount > 0), то организуем цикл сканирования по выборке с одновременным занесением строк выборки в таблицу.
Рис. 10 Цикл выборки в таблицу из RS на основе счетчика записей
Цикл в этом случае организован с помощью оператора Loop, на основе счетчика nCount. Счетчик уменьшается на единицу, а при достижении нуля цикл прерывается (break). На каждом шаге цикла сначала добавляется строка в таблицу (функция - SalTblInsertRow) и в нее выбирается текущая строка выборки (SqlFetchRow). В колонку номера (tblTest.colNumb), известным нам способом заносится номер с точкой. Счетчик цикла уменьшается на единицу. Далее сбрасываются флаги заголовочной колонки для добавляемых записей (SalTblSetFlagsAnyRows). В конце процедуры выборка будет закрыта и курсор освобождается (SqlCommit). Данный вариант организации цикла выборки не единственно возможный, но на наш взгляд при заполнении таблицы наиболее рациональный.
После заполнения таблицы мы модем начинать работать с записями. Если щелкнуть мышкой по строке или заголовочной колонке, то автоматически будут заполнены поля окна (имя, оклад и должность) и указан номер текущей записи (dfNumb). Эти действия поддерживаются процедурами, как реакция на сообщения таблицы. Фрагменты текста даны ниже.
Рис. 11 Обработка сообщений при выделении строки в таблице
В нашем примере мы будем использовать пользовательское сообщение, для заполнения списка должностей. Эта константу (FILL_LIST) нужно определить в разделе системных констант, как показано на рисунке ниже.
Рис. 12 Описание пользовательской константы FILL_LIST
Реакция на данное сообщение, определенная в разделе сообщений комбинированного списка (cmbDolg) показана на рисунке ниже. При поступлении сообщения этого типа список будет заполнен запросом в функции SalListPopulate.
Рис. 13 Заполнение списка при создании и обработке пользовательского сообщения
Теперь рассмотрим процедуры для работы с записями сотрудников. Ниже приведены фрагменты текстов программы для добавления, удаления и изменения записей. Первоначально мы должны определить код должности из связанной таблицы, это делается простым запросом на основе состояния списка должностей. Результат получим в переменной – nCodeDolg. Далее для новой записи мы получаем новый уникальный код на основе запроса в таблице сотрудников (nMaxCode). Затем этот код увеличиваем на единицу. Следующим шагом выполняем запрос добавления записи в БД (INSERT). Так как состояние таблицы должно измениться, то очищаем ее и снова заполняем, но на этот раз с помощью функции SalTblPopulate. Запрос заполнения таблицы аналогичен исходному запросу. При удалении записей достаточно использовать ROWID текущей записи в таблице для выполнения запроса. Удаление выполняется стандартной командой SQL – DELETE. После удаления записи таблица должна быть обновлена аналогичным образом. При редактировании записей, необходимо получить новый код должности и выполнить команду SQL UPDATE, используя соответствующие связующие переменные (поля: dfName , nCodeDol, dfOklad). Код записи редактировать нельзя. После редактирования таблица вновь будет заполнена. В принципе, если объем выборки велик, то можно не заполнять таблицу заново, а использовать специальные функции для ее обновления (SalTblDoInsert, SalTblDoDeletes, SalTblDoUpdate). Но эти функции мы рассмотрим позже в других статьях.
Рис. 14 Процедура добавления новой записи сотрудника
Текст процедуры удаления записей представлен ниже.
Рис. 15 Процедура удаления записи из БД
Текст процедуры редактирования записей представлен ниже.
Рис. 16 Процедура редактирования записи в БД
Ранее мы отмечали, что возможны различные варианты циклов для формирования выборки в таблицу. Пример такого цикла, возможно менее экономичного, представлен на рисунке ниже. Особенностью данного цикла является то, что заранее не определяется объем выборки, а завершение цикла происходит на основе кода возврата полученного при сканировании выборки (nErr = FETCH_EOF). Из-за этого приходиться удалять лишнюю строку, сформированную в цикле. Все другие операции с таблицей идентичны.
За дополнительной информацией обращайтесь в компанию Interface Ltd.
INTERFACE Ltd. |
|