Создание, изменение и удаление хранимых процедур 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Создание, изменение и удаление хранимых процедур



Создание хранимой процедуры предполагает решение следующих задач:

определение типа создаваемой хранимой процедуры: временная или пользовательская. Кроме этого, можно создать свою собственную системную хранимую процедуру, назначив ей имя с префиксом sp_ и поместив ее в системную базу данных. Такая процедура будет доступна в контексте любой базы данных локального сервера;

· планирование прав доступа. При создании хранимой процедуры следует учитывать, что она будет иметь те же права доступа к объектам базы данных, что и создавший ее пользователь;

· определение параметров хранимой процедуры. Подобно процедурам, входящим в состав большинства языков программирования, хранимые процедуры могут обладать входными и выходными параметрами;

· разработка кода хранимой процедуры. Код процедуры может содержать последовательность любых команд SQL, включая вызов других хранимых процедур.

 

Создание новой и изменение имеющейся хранимой процедуры осуществляется с помощью следующей команды:

<определение_процедуры>::=

{CREATE | ALTER } PROC[EDURE] имя_процедуры

[;номер]

[{@имя_параметра тип_данных } [VARYING ]

[=default][OUTPUT] ][,...n]

[WITH { RECOMPILE | ENCRYPTION | RECOMPILE,

ENCRYPTION }]

[FOR REPLICATION]

AS

sql_оператор [...n]

 

Рассмотрим параметры данной команды.

 

Используя префиксы sp_, #, ##, создаваемую процедуру можно определить в качестве системной или временной. Как видно из синтаксиса команды, не допускается указывать имя владельца, которому будет принадлежать создаваемая процедура, а также имя базы данных, где она должна быть размещена. Таким образом, чтобы разместить создаваемую хранимую процедуру в конкретной базе данных, необходимо выполнить команду CREATE PROCEDURE в контексте этой базы данных. При обращении из тела хранимой процедуры к объектам той же базы данных можно использовать укороченные имена, т. е. без указания имени базы данных. Когда же требуется обратиться к объектам, расположенным в других базах данных, указание имени базы данных обязательно.

Номер в имени – это идентификационный номер хранимой процедуры, однозначно определяющий ее в группе процедур. Для удобства управления процедурами логически однотипные хранимые процедуры можно группировать, присваивая им одинаковые имена, но разные идентификационные номера.

Для передачи входных и выходных данных в создаваемой хранимой процедуре могут использоваться параметры, имена которых, как и имена локальных переменных, должны начинаться с символа @. В одной хранимой процедуре можно задать множество параметров, разделенных запятыми. В теле процедуры не должны применяться локальные переменные, чьи имена совпадают с именами параметров этой процедуры.

Для определения типа данных, который будет иметь соответствующий параметр хранимой процедуры, годятся любые типы данных SQL, включая определенные пользователем. Однако тип данных CURSOR может быть использован только как выходной параметр хранимой процедуры, т.е. с указанием ключевого слова OUTPUT.

Наличие ключевого слова OUTPUT означает, что соответствующий параметр предназначен для возвращения данных из хранимой процедуры. Однако это вовсе не означает, что параметр не подходит для передачи значений в хранимую процедуру. Указание ключевого слова OUTPUT предписывает серверу при выходе из хранимой процедуры присвоить текущее значение параметра локальной переменной, которая была указана при вызове процедуры в качестве значения параметра. Отметим, что при указании ключевого слова OUTPUT значение соответствующего параметра при вызове процедуры может быть задано только с помощью локальной переменной. Не разрешается использование любых выражений или констант, допустимое для обычных параметров.

Ключевое слово VARYING применяется совместно с параметром OUTPUT, имеющим тип CURSOR. Оно определяет, что выходным параметром будет результирующее множество.

Ключевое слово DEFAULT представляет собой значение, которое будет принимать соответствующий параметр по умолчанию. Таким образом, при вызове процедуры можно не указывать явно значение соответствующего параметра.

Так как сервер кэширует план исполнения запроса и компилированный код, при последующем вызове процедуры будут использоваться уже готовые значения. Однако в некоторых случаях все же требуется выполнять перекомпиляцию кода процедуры. Указание ключевого слова RECOMPILE предписывает системе создавать план выполнения хранимой процедуры при каждом ее вызове.

Параметр FOR REPLICATION востребован при репликации данных и включении создаваемой хранимой процедуры в качестве статьи в публикацию.

Ключевое слово ENCRYPTION предписывает серверу выполнить шифрование кода хранимой процедуры, что может обеспечить защиту от использования авторских алгоритмов, реализующих работу хранимой процедуры.

Ключевое слово AS размещается в начале собственно тела хранимой процедуры, т.е. набора команд SQL, с помощью которых и будет реализовываться то или иное действие. В теле процедуры могут применяться практически все команды SQL, объявляться транзакции, устанавливаться блокировки и вызываться другие хранимые процедуры. Выход из хранимой процедуры можно осуществить посредством команды RETURN.

Удаление хранимой процедуры осуществляется командой:

DROP PROCEDURE {имя_процедуры} [,...n]

Выполнение хранимой процедуры

 

Для выполнения хранимой процедуры используется команда:

[[ EXEC [ UTE] имя_процедуры [;номер]

[[@имя_параметра=]{значение | @имя_переменной}

[OUTPUT ]|[DEFAULT ]][,...n]

Если вызов хранимой процедуры не является единственной командой в пакете, то присутствие команды EXECUTE обязательно. Более того, эта команда требуется для вызова процедуры из тела другой процедуры или триггера.

Использование ключевого слова OUTPUT при вызове процедуры разрешается только для параметров, которые были объявлены при создании процедуры с ключевым словом OUTPUT.

Когда же при вызове процедуры для параметра указывается ключевое слово DEFAULT, то будет использовано значение по умолчанию. Естественно, указанное слово DEFAULT разрешается только для тех параметров, для которых определено значение по умолчанию.

Из синтаксиса команды EXECUTE видно, что имена параметров могут быть опущены при вызове процедуры. Однако в этом случае пользователь должен указывать значения для параметров в том же порядке, в каком они перечислялись при создании процедуры. Присвоить параметру значение по умолчанию, просто пропустив его при перечислении нельзя. Если же требуется опустить параметры, для которых определено значение по умолчанию, достаточно явного указания имен параметров при вызове хранимой процедуры. Более того, таким способом можно перечислять параметры и их значения в произвольном порядке.

Отметим, что при вызове процедуры указываются либо имена параметров со значениями, либо только значения без имени параметра. Их комбинирование не допускается.

Пример. Процедура без параметров. Разработать процедуру для получения названий и стоимости товаров, приобретенных Ивановым.

CREATE PROC my_proc1

AS

SELECT Товар.Название,

  Товар.Цена*Сделка.Количество

AS Стоимость, Клиент.Фамилия

FROM Клиент INNER JOIN

(Товар INNER JOIN Сделка

ON Товар.КодТовара=Сделка.КодТовара)

ON Клиент.КодКлиента=Сделка.КодКлиента

WHERE Клиент.Фамилия=’Иванов’

 

3.3.2 Понятие и виды каскадных воздействий. Организация выполнения каскадных воздействий

Чтобы предотвратить потерю ссылочной целостности, используется механизм каскадных изменений. Он состоит в обеспечении следующих требовании:

• необходимо запретить изменение поля связи в записи дочерней таблицы без синхронного изменения полей связи в родительской и дочерней таблицах; обычно инициатива изменения поля связи реализуется в записи родительской таблицы;

• при изменении поля связи в записи родительской таблице, следует синхронно изменить значения полей связи в соответствующих записях дочерней таблицы;

• при удалении записи в родительской таблице, следует удалить соответствующие записи в дочерней таблице.

Данные изменения или удаления в записях дочерней таблицы при изменении (удалении) записи родительской таблицы называются каскадными изменениями и каскадными удалениями.

Замечание 1. Существует другая разновидность каскадного удаления: при удалении родительской записи в записях дочерних таблиц значения полей связи обнуляются. Эта разновидность применяется редко.

Замечание 2. Обычно занесение записей в дочернюю таблицу осуществляется так: выбирается значение родительской записи (например, из выпадающего списка), значение поля связи фиксируется и затем автоматически заносится в поля связи дочерних записей. Метод, когда пользователь вручную заносит значения полей связи в дочерние записи, непопулярен: пользователь может внести одинаковое по смыслу, но разное по написанию значение ("Сахар", "сахар"). Много реже практикуется способ ввода дочерних записей без указания значения поля связи. Затем записи родительской и дочерних таблиц "связываются".

Каскадные изменения могут блокироваться: или одновременно изменения и удаления, или изменения или удаления по отдельности. Необходимость разрешения или запрещения каскадных изменений обычно реализуется в СУБД при определении связей между таблицами. Собственно, таким образом и происходит создание ссылочной целостности. Обычно в СУБД для реализации ссылочной целостности в дочерней таблице создают внешний ключ (см. ниже), ссылающийся на родительскую таблицу, и указывают вид каскадных воздействий. В последующем СУБД сама при необходимости реализует каскадные воздействия данного вида для указанных таблиц.

 

3.4 Сортировка, поиск и фильтрация данных в БД и выборках

3.4.1 Различные методы сортировки, поиска и фильтрации данных

 

Сортировка набора данных

Сортировка заключается в упорядочивании записей по определенному полю в порядке возрастания или убывания содержащихся в нем значений. Сортировку можно выполнять и по нескольким полям. Например, при сортировке по двум полям записи сначала упорядочиваются по значениям первого поля, а затем группы записей с одинаковым значением первого поля сортируются по второму полю.

Сортировка наборов данных Table и Query выполняется различными способами.

Сортировка наборов данных Table выполняется автоматически по текущему индексу. При смене индекса происходит автоматическое переупорядочивание записей. Таким образом, сортировка возможна по полям, для которых создан индекс. Для сортировки по нескольким полям нужно создать индекс, включающий эти поля.

Направление сортировки определяет параметр ixDescending текущего индекса, по умолчанию он выключен, и упорядочивание выполняется в порядке возрастания значений. Если для индекса признак ixDescending включен, то сортировка выполняется в порядке убывания значений.

Поля, по которым сортируются записи, устанавливаются через свойство IndexName. При отсутствии сортировки этому свойству присваивается пустая строка. Для таблиц Paradox это означает сортировку по первому полю. Для таблиц dBase записи располагаются в порядке их поступления в файл таблицы.

Список полей, по которым выполняется сортировка, указывается в операнде ORDER BY. Порядок полей в этом операнде определяет порядок сортировки: сначала записи упорядочиваются по значениям поля, указанного в этом списке первым, затем записи, имеющие одинаковое значение первого поля, упорядочиваются по второму полю и т. д.

Поля в списке обозначаются именами или номерами, которые соответствуют номерам в списке полей после слова SELECT.

По умолчанию сортировка происходит в порядке возрастания значений полей. Для указания обратного порядка сортировки по какому-либо полю нужно указать после имени этого поля описатель DESC.

Замечание

В отличие от набора данных Table, средствами языка SQL можно выполнять сортировку для набора данных Query и по неиндексированным полям. Однако по индексированным полям таблицы сортировка выполняется быстрее. При этом состав полей индекса должен соответствовать списку полей, указанных в операнде ORDER BY.

При разработке приложения управление сортировкой осуществляется посредством различных элементов формы, например, кнопок и переключателей.

Когда в SQL-запросе отсутствует параметр ORDER, по умолчанию записи упорядочиваются по первому полю. Поэтому в рассматриваемом примере отсутствие сортировки и сортировка по полю Name приводят к одинаковому результату.

Поиск записей

Поиск — это нахождение записи, удовлетворяющей определенным условиям, и возврат значений ее полей с возможным переходом на найденную запись. Отметим, что поиск можно вести по одним полям, а возвращать значения других полей. Составы полей для поиска и для возврата значений в общем случае не совпадают.

При организации поиска записей важное значение имеет наличие индекса для полей, по которым ведется поиск. Индексирование значительно повышает скорость обработки данных, кроме того, ряд методов может работать только с индексированными полями.

Поиск в наборах данных

Для поиска записей по полям служат методы Locate и Lookup, причем поля могут быть неиндексированными.

Функция Locate (const KeyFields: String; const KeyValues: Variant; Options: TLocateOptions): Boolean ищет запись с заданными значениями полей. Если удовлетворяющие условиям поиска записи существуют, то указатель текущей записи устанавливается на первую из них. Если запись найдена, функция возвращает значение True, в противном случае — значение False. Список полей, по которым ведется поиск, задается в параметре KeyFields, поля разделяются точкой с запятой. Параметр KeyValues типа variant указывает значения полей для поиска. Если поиск ведется по одному полю, то параметр содержит одно значение, соответствующее типу поля, заданного для поиска.

Параметр options позволяет задать значения, которые обычно используются при поиске строк. Этот параметр принадлежит к множественному типу TLocateOptions и принимает комбинации следующих значений:

1. locaseinsensitive —регистр букв не учитывается;

2. loPartiaiKey — допускается частичное совпадение значений.

 

При поиске по нескольким полям в методе Locate параметр KeyValues является массивом значений типа variant, в котором содержится несколько элементов.

Для приведения к типу вариантного массива используется функция varArrayOf. Значения разделяются запятыми и заключаются в квадратные скобки, порядок значений должен соответствовать порядку полей параметра KeyFieids. Обычно при разработке приложений пользователю предоставляется возможность влиять на процесс поиска с помощью управляющих элементов, расположенных на форме. При этом действия пользователя по управлению поиском в наборе данных мало чем отличаются от аналогичных действий при выполнении фильтрации.

Замечание

Если имя поля или тип значения заданы неправильно, то при попытке выполнить метод Locate генерируется исключительная ситуация.

Метод Locate позволяет вести поиск по любым полям, однако если поля индексированы или являются частью некоторого индекса, то соответствующий индекс при поиске используется автоматически. При этом также автоматически записи набора данных сортируются по указанному индексу. В результате, если условиям поиска удовлетворяет несколько записей, то будет найдена и установлена текущей первая в порядке сортировки запись. При использовании другого индекса порядок расположения записей, удовлетворяющих условиям поиска, может измениться, и будет найдена другая запись.

Для поиска в наборе данных также используется метод Lookup, который работает аналогично методу Locate. Функция Lookup (const KeyFields: String; const KeyValues: Variant; const ResultFields: String): Variant осуществляет поиск записи, удовлетворяющей определенным условиям, но, в отличие от метода Locate, не перемещает указатель текущей записи на найденную запись, а считывает информацию из полей записи. Еще одно отличие между двумя методами заключается в том, что метод Lookup осуществляет поиск на точное соответствие значений для поиска и значений в полях записей с учетом регистра букв.

Параметры KeyFields и KeyValues имеют такое же назначение, как и в методе Locate, и используются аналогичным образом.

В параметре ResultFields через точку с запятой перечисляются названия полей, значения которых будут получены в случае успешного поиска. Эти значения считываются из первой найденной записи, удовлетворяющей условиям поиска. Порядок перечисления полей в ResultFields может отличаться от порядка полей в наборе данных. Например, если набор данных имеет поля Code, Name, Salary И Note, то в ResultFields можно задать Salary и Name.

В случае удачного поиска метод Lookup в качестве результата возвращает значение типа variant, размерность которого зависит от списка полей ResultFields. Если список содержит одно значение, то метод возвращает значение одного поля, если в списке задано несколько полей, то метод возвращает массив variant, число элементов которого совпадает с числом полей в списке ResultFields.

При неудачном поиске метод Lookup возвращает значение Null. Для анализа такого результата можно использовать функцию VarlsNul (const V: Variant): Boolean, возвращающую значение True при значении параметра v, равном Null.

Не следует путать Null, соответствующее пустому (нулевому) значению, и Nil, означающее отсутствие значения.

Замечание

Если из найденной записи считываются значения нескольких полей, то даже в случае успешного поиска часть полей может быть не определена и содержать пустые значения. Поэтому при операциях с элементами массива variant следует проверять значение каждого из них на равенство Null.

Поиск по индексным полям

Для набора данных Table имеются методы, позволяющие вести поиск записей только по индексным полям. Перед вызовом любого из этих методов следует установить в качестве текущего индекс, построенный по используемым для поиска полям. Методы поиска можно разделить на две группы, в первую из которых входят методы FindKey, SetKey, EditKey и GotoKey, предназначенные для поиска на точное соответствие, а другую образуют методы FindNearest, SetNearest, EditNearest и GotoNearest, допускающие только частичное совпадение заданных для поиска значений и значений полей записей.

Метод FindKey (const KeyValues: array of const): Boolean выполняет поиск в наборе данных Table записи, у которой значения полей совпадают со значениями, указанными в параметре KeyValues.

Список полей для поиска не задается, а берутся индексные поля в соответствии с текущим индексом. Если поиск завершился успешно, то найденная запись становится текущей, а метод возвращает значение True. При неудачном поиске указатель текущей записи не перемещается, а метод возвращает значение False.

Если заданным условиям поиска соответствует несколько записей, то указатель текущей записи устанавливается на первую из них. Порядок сортировки и, соответственно, порядок расположения записей в наборе данных определяется текущим индексом, по которому и ведется поиск.

Метод setKey переводит набор данных в режим поиска записи dsSetKey, этот метод вызывается один раз для текущего индекса. Впоследствии для перехода в режим поиска можно вызывать метод EditKey. Если набор данных находится в режиме поиска, значения полей устанавливаются с помощью операторов присваивания. Метод GotoKey: Boolean выполняет собственно поиск записи, удовлетворяющей заданному условию. Использовать комбинацию названных методов менее удобно, чем метод FindKey.

Метод FindNearest, в отличие от метода FindKey, производит поиск значений полей записей набора данных Table, которые только частично совпадают со значениями, заданными для поиска. Сравнение проводится, начиная с первого стоящего в поле символа. Поиск по частичному совпадению можно применять к строкам или к данным других типов, например, целым. Поиск с помощью процедуры FindNearest (const KeyValues: array of const) всегда является успешным и перемещает указатель текущей записи на запись, в наибольшей степени отвечающую условиям поиска.

Вместо метода FindNearest можно использовать комбинацию методов SetNearest, EditNearest и GotoNearest, pабота c которыми аналогична работе с соответствующими методами поиска на точное соответствие значений полей.

При поиске по нескольким полям текущего индекса используется свойство KeyFieidCount типа Boolean, указывающее, сколько полей индекса, начиная с первого, участвует в поиске. По умолчанию поиск осуществляется по всем полям текущего индекса.

Фильтрация записей

Фильтрация — это задание ограничений для записей, отбираемых в набор данных. Напомним, что набор данных представляет собой записи, выбранные из одной или нескольких таблиц. Состав записей в наборе данных в данный момент времени зависит от установленных ограничений, в том числе и от фильтров. Система Delphi дает возможность осуществлять фильтрации записей:

1. по выражению;

2. по диапазону.

По умолчанию фильтрация записей не ведется, и набор данных Table содержит все записи связанной с ним таблицы БД, а в набор данных Query включаются все записи, удовлетворяющие SQL-запросу, содержащемуся в свойстве SQL.

Фильтрация похожа на SQL-запросы, но является менее мощным средством. По сравнению с SQL-запросами фильтрация менее эффективна, т. к. ограничивает количество записей, видимых в наборе.

Фильтрация по выражению

При использовании фильтрации по выражению набор данных ограничивается записями, удовлетворяющими выражению фильтра, задающему условия отбора записей.

Достоинством фильтрации по выражению является то, что она применима к любым полям, в том числе к неиндексированным. В связи с тем, что в процессе отбора просматриваются все записи таблицы, фильтрация по выражению эффективна при небольшом количестве записей.

Для задания выражения фильтра используется свойство Filter типа string. Фильтр представляет собой конструкцию, в состав которой могут входить сле-дующие элементы:

1. имена полей таблиц;

2. литералы;

3. операции сравнения;

4. арифметические операции;

5. логические операции;

6. круглые и квадратные скобки.

Если имя поля содержит пробелы, то его заключают в квадратные скобки, в противном случае квадратные скобки необязательны.

Литерал представляет собой значение, заданное явно, например, число, строка |или символ. Отметим, что имена переменных в выражении фильтра использо-вать нельзя. Если в фильтр требуется включить значение переменной или свой-ства какого-либо компонента, то это значение должно быть преобразовано в строковый тип.

Операции сравнения представляют собой обычные для языка Pascal отношения >> => <=> >=и о.

Арифметическими являются операции +, -, * и / (сложения, вычитания, умно-жения и деления, соответственно).

В качестве логических операций можно использовать AND, OR и NOT (логическое умножение, сложение и отрицание, соответственно).

Круглые скобки применяются для изменения порядка выполнения арифметиче ских и логических операций. Если выражение фильтра не позволяет сформировать сложный критерий фильт-рации, то в дополнение к нему можно использовать обработчик события OnFilterRecord.

Для активизации и деактивизации фильтра применяется свойство Filter типа boolean. По умолчанию это свойство имеет значение False, и фильтрация выключена. При установке свойству Filtered значения True фильтрация включается, и в набор данных отбираются записи, которые удовлетворяют фильтру, записанному в свойстве Filter. Если выражение фильтра не задано (по умолчанию), то в набор данных попадают все записи.

Параметры фильтрации задаются с помощью свойства FilterOptions типа TFilterOptions. Это свойство принадлежит к множественному типу и может принимать комбинации двух значений:

1. focaseinsensitive — регистр букв не учитывается, т. е. при задании фильтра Post = 'Водитель' слова Водитель, ВОДИТЕЛЬ или водитель будут восприняты как одинаковые. Значение focaseinsensitive рекомендуется отключать, чтобы различать слова, написанные в различных регистрах.

2. foNoPartiaicompare — выполняется проверка на полное соответствие содержимого поля и значения, заданного для поиска. Обычно применяется для строк символов. Если известны только первые символы (или символ) строки, то нужно указать их в выражении фильтра, заменив остальные символы на звездочки * и выключив значение foNoPartiaicompare. Например, при выключенном значении foNoPartiaicompare для фильтра Post = ‘в*’ будут отобраны записи, у которых в поле Post содержатся значения водитель, вод., Вод-ль ИЛИ Врач.

По умолчанию все параметры фильтра выключены, и свойство FilterOptions имеет значение [ ].

Часто удобно предоставить пользователю список готовых выражений (шаблонов) для выбора. При этом пользователь получает также возможность редактировать выбранное выражение и корректировать весь список. Такой режим реализуется, например, с помощью компонентов comboBox и Memo.

Если набор условий фильтрации ограничен и не изменяется, то пользователь может управлять отбором записей с помощью таких компонентов, как независимые (checkBox) и зависимые (RadioButton) переключатели.

В обработчике события onFilterRecord можно определять дополнительные к выражению фильтра условия фильтрации. По своему действию основные и дополнительные условия как бы соединены логической операцией AND, т. е. для отбора записи в набор данных требуется соблюдение обоих условий. В отличие от выражения фильтра, в обработчике события OnFilterRecord можно кодировать любые сколь угодно сложные проверки с помощью средств языка Object Pascal. Таким образом, набор данных Table допускает два способа задания условий фильтрации: с помощью выражения фильтра Filter и в обработчике события OnFilterRecord.

В случае набора данных Query для отбора записей можно использовать:

1. SQL-запрос;

2. обработчик события OnFilterRecord;

3. выражение фильтра.

Напомним, что для связанных таблиц на отбор записей в набор данных также влияет ограничение, налагаемое отношением "главный-подчиненный" между таблицами БД.

Фильтрация по диапазону

При фильтрации по диапазону в набор данных включаются записи, значения полей которых попадают в заданный диапазон, т. е. условием фильтрации является выражение вида значение > нижней границы AND значение < верхней границы (вместо операций сравнения < > могут указываться и операции <= >=). Такая фильтрация применяется к наборам данных Table.

Достоинством фильтрации по диапазону является высокая скорость обработки записей. В отличие от фильтрации по выражению, когда последовательно просматриваются все записи таблицы, фильтрация по диапазону ведется индексно-последовательным методом, поэтому этот способ фильтрации применим только для индексированных полей. Индекс поля, диапазон которого задан в качестве критерия для отбора записей, должен быть установлен как текущий с помощью свойства indexName или indexFieldNames. Если текущий индекс не установлен, то по умолчанию используется главный индекс.

Для включения и выключения фильтрации по диапазону применяются методы ApplyRange и CanceiRange. Первый из них активизирует фильтр, а второй — деактивизирует. Предварительно для индексного поля (полей), по которому выполняется фильтрация, следует задать диапазон допустимых значений.

Методы SetRangeStart и SetRangeEnd устанавливают нижнюю и верхнюю границу диапазона, соответственно. Названные процедуры не имеют параметров, и для задания границ диапазона используется просто оператор присваивания. При этом методы SetRangeStart и SetRangeEnd переводят набор данных в режим dsSetKey.

Для изменения предварительно установленных границ диапазона предназначены методы EditRangeStart и EditRangeEnd, действие которых аналогично действию методов SetRangeStart и SetRangeEnd, соответственно.

Когда одна из границ диапазона не задана, то диапазон открыт, т. е. нижняя граница становится равной минимально возможному, а верхняя граница — максимально возможному значению этого поля.

Если фильтрация выполняется одновременно по нескольким полям, то после вызова методов SetRangeStart или SetRangeEnd должны стоять несколько опера-торов присваивания, каждый из которых определяет границу по одному полю. Предварительно в качестве текущего должен быть установлен индекс, построенный по этим полям.

Замечание

Если текущий индекс был изменен, то фильтрация по предыдущему индексу перестает действовать, и в наборе данных будут видимы все записи. При возвращении к прежнему текущему индексу фильтрация также не действует, несмотря на то, что диапазон был задан при предыдущей фильтрации.

При выполнении фильтрации по диапазону возможен отбор записей по частичному совпадению значений символьных полей, когда задаются только начальные символы строки. В отличие от фильтрации по выражению, при фильтрации по диапазону отсутствует свойство, аналогичное 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 генерируется сразу после открытия набора данных. Это событие можно использовать, например, для выдачи пользователю сообщения о возможности работы с данными.



Поделиться:


Последнее изменение этой страницы: 2021-12-15; просмотров: 39; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.142.174.55 (0.093 с.)