Если текущий индекс был изменен, то фильтрация по предыдущему индексу перестает действовать, и в наборе данных будут видимы все записи. При возвращении к прежнему текущему индексу фильтрация также не действует, несмотря на то, что диапазон был задан при предыдущей фильтрации.
При выполнении фильтрации по диапазону возможен отбор записей по частичному совпадению значений символьных полей, когда задаются только начальные символы строки. В отличие от фильтрации по выражению, при фильтрации по диапазону отсутствует свойство, аналогичное FilterOptions с параметром foCaselnsensitive.
В качестве нижней границы указываются символы, являющиеся началом строки, а для получения значения верхней границы можно добавить справа от них строку яяя. Как правило, символьные значения в полях для фильтрации не могут содержать несколько идущих подряд букв я, а код прописной буквы я больше, чем коды других букв, в результате в набор данных попадут записи, поля которых содержат значения, начинающиеся с заданных символов. Если в полях таблицы могут оказаться строки, включающиеся в себя добавленную строку яяя, то можно увеличить количество букв я в строке, добавляемой при формировании верхней границы диапазона. При использовании осмысленных слой вероятность такого совпадения близка к нулю, в крайнем случае в отфильтрованном наборе данных может оказаться несколько лишних записей.
В случае набора данных Query, используя средства SQL, можно отбирать записи по частичному совпадению не только начальных символов строки, но и по вхождению заданных символов в любое место строки.
3.4.2 Особенности использования каждого метода управления данными
Таблицы БД располагаются на диске и являются физическими объектами. Для операций с данными, содержащимися в таблицах, используются наборы данных. В терминах системы Delphi набор данных представляет собой совокупность записей, взятых из одной или нескольких таблиц БД. Записи, входящие в набор данных, отбираются по определенным правилам, при этом в частных случаях набор данных может включать в себя все записи из связанной с ним таблицы или не содержать ни одной записи. Набор данных является логической таблицей, с которой можно работать при выполнении приложения. Взаимодействие таблицы и набора данных напоминает взаимодействие физического файла и файловой переменной.
В Delphi для работы с наборами данных служат такие компоненты, как Table, Query, UpdateSQL, DecisionQuery или StoredProc.
Базовые возможности доступа к БД обеспечивает класс TDataSet, представляющий наборы данных в виде совокупности строк и столбцов (записей и полей). Этот класс содержит в себе основные средства навигации (перемещения) и редактирования наборов данных.
Расположение БД, с таблицами которой выполняются операции, указывает свойство DatabaseName типа string. Значением свойства является имя каталога, в котором находится БД (файлы ее таблиц), или псевдоним, ссылающийся на этот каталог. Если для БД определен псевдоним, то его можно выбрать через Инспектор объектов в раскрывающемся списке.
Для компонента Table использование свойства DatabaseName является единственной возможностью задать местонахождение таблиц БД. Для компонента Query дополнительно можно указать в запросе SQL путь доступа к каждой таблице.
В зависимости от ограничений и критерия фильтрации один и тот же набор данных в разные моменты времени может содержать различные записи. Число записей, составляющих набор данных, определяет свойство RecordCount типа Longint. Это свойство доступно для чтения при выполнении приложения. Управление числом записей в наборе данных осуществляется косвенно — путем отбора записей тем или иным способом, например, с помощью фильтрации или SQL-запроса (для компонента Query).
Для локальных таблиц dBase или Paradox составляющие набор данных записи последовательно нумеруются, отсчет начинается с единицы. Номер записи в наборе данных определяет свойство RecNo типа Longint, которое доступно во время выполнения программы.
Замечание
При изменении порядка сортировки или фильтрации нумерация записей также изменяется.
Для выполнения операций с наборами данных используются два способа доступа к данным:
1. навигационный;
2. реляционный.
Навигационный способ доступа заключается в обработке каждой отдельной записи набора данных. Этот способ обычно используется в локальных БД или в удаленных БД небольшого размера. При навигационном способе доступа каждый набор данных имеет невидимый указатель текущей записи. Указатель определяет запись, с которой могут выполняться такие операции, как редактирование или удаление. Поля текущей записи доступны для просмотра. Например, компоненты DBEdit и DBText отображают содержимое соответствующих полей именно текущей записи. Компонент DBGrid указывает текущую запись с помощью специального маркера.
В разрабатываемом приложении навигационный способ доступа к данным можно реализовать, используя любой из компонентов таblе или Query.
Реляционный способ доступа основан на обработке группы записей. Если требуется обработать одну запись, все равно обрабатывается группа, состоящая из одной записи. При реляционном способе доступа используются SQL-запросы, поэтому его называют также SQL-ориентированным. Реляционный способ доступа ориентирован на работу с удаленными БД и является для них предпочтительным. Однако его можно использовать и для локальных БД.
Реляционный способ доступа к данным в приложении можно реализовать с помощью компонента Query.
Состояния наборов данных
Наборы данных могут находиться в открытом или закрытом состояниях, на что указывает свойство Active типа Boolean. Если свойству Active установлено значение True, то набор данных открыт. Открытый компонент Table содержит набор данных, соответствующий данным таблицы, связанной с ним через свойство TableName. Для открытого компонента Query набор данных соответствует результатам выполнения SQL-запроса, содержащегося в свойстве SQL этого компонента. Если свойство Active имеет значение False (по умолчанию), то набор данных закрыт, и его связь с БД разорвана. Набор данных может быть открыт на этапе разработки приложения. Если при этом к набору данных через источник данных DataSource подключены визуальные компоненты, например, DBGrid или DBEdit, то они отображают соответствующие данные таблицу БД.
Если по каким-либо причинам открытие набора данных невозможно, то при попытке установить свойству Active значение True выдается сообщение об ошибке, а свойство Active сохраняет значение False. Одной из причин невозможности открытия набора данных может являться неправильное значение свойства TableName или SQL.
Управлять состоянием набора данных можно также с помощью методов open и Close.
Процедура open открывает набор данных, ее вызов эквивалентен установке свойству Active значения True. При вызове метода Open генерируются события BeforeOpen и AfterOpen типа TDataSetNotifyEvent и соответственно вызываются процедуры-обработчики этих событий.
Процедура close закрывает набор данных, ее вызов эквивалентен установке свойству Active значения False. При вызове метода close генерируются события Beforeciose и Afterdose типа TDataSetNotifyEvent, а также вызываются процедуры-обработчики этих событий.
Событие BeforeOpen возникает непосредственно перед открытием набора данных. В обработчике этого события можно выполнить проверку определенных условий, и если они не соблюдаются, то открытие набора данных может быть запрещено.
Событие AfterOpen генерируется сразу после открытия набора данных. Это событие можно использовать, например, для выдачи пользователю сообщения о возможности работы с данными.
Отметим, что закрытие набора данных автоматически не сохраняет текущую запись, т. е. если набор данных при закрытии находился в режимах редактирования или вставки, то произведенные изменения данных в текущей записи будут потеряны. Поэтому перед закрытием набора данных нужно проверять его режим и при необходимости принудительно вызывать метод Post, сохраняющий сделанные изменения. Одним из вариантов сохранения изменений является вызов метода Post в обработчике события Beforeciose, возникающего непосредственно перед закрытием набора данных. Событие Afterciose возникает сразу после закрытия набора данных, и его можно использовать для выдачи пользователю соответствующих сообщений.
Необходимо иметь в виду, что если при работе приложения используется большое число таблиц, то выдача подобных сообщений может затруднять действия пользователя. Поэтому программист должен предусмотреть возможность отключения выдачи сообщений.