Методы объекта Recordset
У объекта Recordset много свойств, много и методов. С некоторыми из них мы уже знакомы, поскольку они появлялись в примерах. Теперь приступим к их систематическому рассмотрению. С помощью методов можно выполнять все необходимые операции над набором записей - перемещаться по набору, находить нужные записи, создавать новые записи и удалять существующие, менять содержимое записей и передавать состояние набора в базу данных. Начнем наше рассмотрение:
- Sub AddNew([FieldList], [Values]), Sub Delete([AffectRecords As AffectEnum = adAffectCurrent]). Метод AddNew позволяет добавлять новые записи в набор. Конечно, для применения метода объект Recordset должен иметь статус обновляемого набора, что означает, что для него должен быть установлен соответствующий тип курсора. Можно проверить, допускает ли Провайдер добавление записей. Метод Support, о котором еще предстоит разговор, позволяет выяснить поддерживается ли Провайдером то или иное свойство. В данном случае для того, чтобы проверить возможность создания новых записей в наборе, его следует вызвать, задав в качестве аргумента константу adAddNew.
Что следует сделать, чтобы набор был обновляемым? Я напомню, что создать объект Recordset можно разными способами. Он создается при вызове методов Execute объектов Connection и Command, его можно создать, вызвав метод Open объекта Recordset. В примерах, которые я приводил ранее, это объект создавался при вызове методов Execute. Но, заметьте, объект, создаваемый таким способом всегда имеет статический тип курсора и не может обновляться. Для создания объекта Recordset, допускающего обновление, всегда нужно применять метод Open, задавая динамический тип курсора в момент открытия.
Метод AddNew можно вызывать без аргументов. В этом случае созданная новая запись становится текущей, ее поля можно заполнить обычным способом. Для того чтобы содержимое записи было перенесено в базу данных, следует вызвать метод Update. Можно предусмотреть возможность пакетного обновления и использовать метод UpdateBatch для передачи в базу данных группы записей. Приведу пример, в котором в базу данных добавляется новая запись и корректируется значение отдельных полей в некоторых записях:
Public Sub CreateNewRecords() 'добавление и изменение записей базы данных Dim recExist As Boolean 'Создать соединение CreateConnection 'Создать команду 'задание свойств объекта Command Cmd1.ActiveConnection = Con1 Cmd1.CommandText = "Select * From [Книги]" Cmd1.CommandType = adCmdText 'Открытие обновляемого объекта Recordset With Rst1 .Open Source:=Cmd1, CursorType:=adOpenDynamic, _ LockType:=adLockOptimistic 'Узнаем характеристики набора Debug.Print .Supports(adAddNew) Debug.Print .LockType Debug.Print .CursorType 'Изменение записей recExist = False .MoveFirst Do While Not .EOF 'Обработка текущей записи If !Название = "Офисное программирование" Then recExist = True If ![Год издания] < 2000 And !Цена < 100 Then !Цена = !Цена * 2 .Update End If .MoveNext Loop If Not recExist Then .AddNew !Автор = "Владимир Биллиг" !Название = "Офисное программмирование" ![Год издания] = 2001 ![Число страниц] = 599 !Цена = 150 .Update End If End With End Sub
Заметьте, здесь метод AddNew, вызываемый без параметров, создал новую запись в наборе, она стала текущей, обычным способом заполнены поля этой записи, затем вызван метод Update для переноса записи в базу данных. Этот же метод использовался для изменения в базе данных значения поля "Цена" ряда записей.
При вызове метода AddNew можно задавать аргументы. Параметры метода имеют следующий смысл:
- FieldList - имя поля или массив таких имен. Вместо имен можно задавать порядковые номера полей.
- Values - значение поля или массив значений. Если аргументы задаются, то должны быть заданы оба аргумента, и они должны быть согласованы обычным образом - по числу элементов в массиве, тип значения должен также соответствовать типу поля.
Когда метод AddNew вызывается с аргументами, то создается запись с уже заполненными полями, для нее автоматически вызывается метод Update, так что нет необходимости вызывать его самостоятельно - эту заботу берет на себя система. Приведу пример такого способа добавления записей в набор и базу данных:
Public Sub CreateNewRecords2() 'добавление и изменение записей базы данных Dim recExist As Boolean 'Создать соединение CreateConnection 'Создать команду 'задание свойств объекта Command Cmd1.ActiveConnection = Con1 Cmd1.CommandText = "Select * From [Книги]" Cmd1.CommandType = adCmdText 'Открытие обновляемого объекта Recordset With Rst1 .Open Source:=Cmd1, CursorType:=adOpenDynamic, _ LockType:=adLockOptimistic
recExist = False .MoveFirst Do While Not .EOF 'Проверка существования записи If !Название = "Война и мир" Then recExist = True .MoveNext Loop If Not recExist Then .AddNew Array("Автор", "Название", "Год издания", _ "Число страниц", "Цена"), _ Array("Лев Толстой", "Война и мир", 2001, 799, 220) End If End With End Sub
На эти примеры я еще буду ссылаться при рассмотрении других методов объекта Recordset. Если метод AddNew добавляет записи, то обратный к нему метод Delete позволяет удалять записи из набора и соответственно из базы данных. Я не буду останавливаться на деталях, а продолжу рассмотрение других методов объекта Recordset.
Sub Cancel(), Sub CancelBatch([AffectRecords As AffectEnum = adAffectAll]), Sub CancelUpdate(). Эта группа методов позволяет отменить выполнение метода, в частности отменить проделанную работу по обновлению отдельной записи или пакета записей, если в процессе этой работы становится ясно, что вызывать соответствующий метод Update не следует. Метод CancelUpdate обычно вызывается, когда операция Update или Delete завершилась неуспехом, о чем можно узнать, анализируя свойство EditMode, указывающее на незавершенность состояния редактирования. Function Clone([LockType As LockTypeEnum = adLockUnspecified]) As Recordset. Позволяет создать дубликат набора записей. Дубликат может иметь другие права доступа и использоваться, например, только для чтения.Sub Open([Source], [ActiveConnection], [CursorType As CursorTypeEnum = adOpenUnspecified], [LockType As LockTypeEnum = adLockUnspecified], [Options As Long = -1]), Sub Close(). Метод Open является одним из основных способов создания объекта Recordset. Соответствующая объектная переменная, конечно, должна быть создана, а в момент открытия, используя параметры метода, создается реальный набор записей. Первые два параметра задают источник данных и активное соединение. Источником может быть ссылка на объект Command, SQL-оператор, хранимая процедура. В вышеприведенном примере в качестве источника задавался объект Command, заметьте, в этом случае задавать активное соединение не следует, оно определено в объекте Command. Два следующих параметра задают тип курсора и тип доступа к данным. О важности задания этих параметров я уже говорил, - без них не обойтись, при создании обновляемого набора записей. Последний параметр Options должен быть задан в тех случаях, когда первый параметр Source не является ссылкой на объект Command, в этом случае он задает способ интерпретации первого параметра, принимая значения констант из перечислений CommandTypeEnum и ExecuteOptionEnum. Приведу еще один пример открытия объекта Recordset, когда первый параметр не является объектом Command:
Public Sub CreateRst2() 'Создать соединение CreateConnection ' Открытие объекта Recordset With Rst1 .Open Source:="Select * From [Заказчики]", ActiveConnection:=Con1, _ CursorType:=adOpenStatic, Options:=adCmdText .MoveFirst Do While Not .EOF 'Печать поля записи Debug.Print !Название .MoveNext Loop End With End Sub
В этом примере источник данных задается SQL-оператором, а последний параметр указывает способ интерпретации, имея чаще всего используемое значение - adCmdText.
Метод Close позволяет закрыть ранее открытый объект, освобождая ресурсы.Function CompareBookmarks(Bookmark1, Bookmark2) As CompareEnum. Поскольку внутреннее представление закладок зависит от Провайдера, то самому выполнять операции сравнения закладок невозможно. Для этих целей и используется метод CompareBookmarks, позволяющий сравнивать закладки, принадлежащие одному и тому же набору Recordset или набору и его клону. Фактически закладки передаются Провайдеру, который и возвращает результат сравнения. Значением результата является одна из констант перечисления CompareEnum: adCompareEqual, adCompareGreaterThan, adCompareLessThan, adCompareNotComparable, adCompareNotEqual. Sub Find(Criteria As String, [SkipRecords As Long], [SearchDirection As SearchDirectionEnum = adSearchForward], [Start]). Если для выполнения операций сортировки и фильтрации используются свойства объекта Recordset, то для поиска используются его методы. Метод Find позволяет найти в наборе первую строку, удовлетворяющую критерию поиска, где критерий задается первым параметром метода. Критерий ограничен, - позволяет задать условие поиска только по одному полю, он задается строкой, имеющий следующий синтаксис: <Имя поля> Оператор <Значение поля>, где оператор может быть одной из операций сравнения либо оператором Like, задающим сравнение с шаблоном. Параметры SkipRecords и Start позволяют задать начало поиска. Первый из них указывает, сколько записей следует пропустить, начиная от текущей, чтобы начать поиск. Если задан параметр Start, то поиск начинается с записи, заданной этим параметром. Параметр SearchDirection указывает направление поиска, - вперед или назад от начала поиска. Поиск заверша ется, когда найдена запись, удовлетворяющая критерию, или поиск достиг конца набора записей. Так что неуспех можно определить по истинности EOF или BOF в зависимости от направления поиска. В случае успеха искомая запись становится текущей.Function GetRows([Rows As Long = -1], [Start], [Fields]). Этот метод позволяет создать из набора записей переменную VBA - двумерный массив, состоящий из строк и столбцов набора. Первый параметр указывает число строк, переписываемых из набора в массив. Значение по умолчанию этого параметра указывает, что переписываются все строки до конца набора. Если Провайдер поддерживает закладки, то можно задать закладку, как значение параметра Start, определяющую строку, начиная с которой набор будет переписываться в массив. Можно в массив записать выборочные поля набора записей, задав параметр Fields соответствующим образом - в виде массива имен или порядковых номеров переписываемых полей.Function GetString([StringFormat As StringFormatEnum = adClipString], [NumRows As Long = -1], [ColumnDelimeter As String], [RowDelimeter As String], [NullExpr As String]) As String. Если предыдущий метод позволяет преобразовать набор записей в двумерный массив, то метод GetString позволяет конвертировать набор записей в строку. Не буду останавливаться на деталях такого преобразованияSub Move(NumRecords As Long, [Start]), Sub MoveFirst(), Sub MoveLast(),Sub MoveNext(),Sub MovePrevious(). Эта группа методов позволяет организовать перемещение по записям набора. Методы неоднократно появлялись в наших примерах, и я полагаю, семантика их не нуждается в дополнительных пояснениях.Function NextRecordset([RecordsAffected]) As Recordset. Метод Execute объекта Command или метод Open объекта Recordset может выполнять составные команды, возвращающие множество наборов данных. Например, командой может быть составной оператор SQL вида: "Select * From [Книги]; Select * From [Заказчики]". В таких случаях необходимо вызвать метод NextRecordset для получения очередного набора записей. Если множество наборов исчерпано, то метод возвращает значение Nothing. Синтаксически очередной объект может связываться с той же объектной переменной, если старый набор уже не нужен. Sub Requery([Options As Long = -1]). Вызов этого метода эквивалентен последовательности вызовов методов Open и Close. Он позволяет обновить состояние набора, синхронизируя его с текущим состоянием базы данных. Параметр Options определяет специфику выполнения обновления, его возможные значения задаются суммой констант из перечислений ExecuteOptionEnum и CommandTypeEnum. Так, например, значение adAsyncExecute указывает, что обновление будет идти асинхронно и о его завершении можно будет узнать, когда вызовется обработчик события RecordsetChangeComplete.Sub Resync([AffectRecords As AffectEnum = adAffectAll], [ResyncValues As ResyncEnum = adResyncAllValues]). Еще один способ синхронизации данных набора записей и базы данных. В отличие от выше описанного метода Requery запрос повторно не выполняется, - восстанавливается значения только тех записей, которые есть в наборе. Поэтому, если запись набора будет удалена другим пользователем, то возникнет ошибка, информация о которой сохранится в коллекции Errors. Метод полезен при работе со статическим курсором или курсором типа Forward Only.Sub Save([Destination], [PersistFormat As PersistFormatEnum = adPersistADTG]). Позволяет сохранить набор записей в файле или объекте Stream. Параметр Destination задает полный путь к файлу, в котором должен быть сохранен объект Recordset или ссылку на объект Stream. Второй параметр задает формат сохранения - XML или ADTG.Sub Seek(KeyValues, [SeekOption As SeekEnum = adSeekFirstEQ]). Еще один, наряду с методом Find, метод поиска записи в наборе. Напомню, поля в таблицах базы данных могут быть индексированными. Индексы позволяют организовать быстрый поиск нужной записи. Метод Seek позволяет по ключевым значениям индексируемых полей найти запись в наборе и сделать ее текущей. В его первом параметре KeyValues задается массив значений полей, составляющих индекс. Параметр SeekOption задает тип сравнения между столбцами индекса и соответствующими значениями KeyValues.
Метод используется в сочетании со свойством Index, которое задает соответствующий индекс.
Поскольку не все Провайдеры поддерживают работу с индексами, то перед вызовом метода полезно, как обычно, вызвать метод Supports с константой adSeek или adIndex, чтобы выяснить возможность такого вызова в используемом контексте. Провайдер базы данных Access не поддерживает работу с индексами и для него единственным методом поиска является метод Find.Function Supports(CursorOptions As CursorOptionEnum) As Boolean. Метод, позволяющий выяснить возможности Провайдера в данном контексте. Параметр CursorOptions задает одно из возможных свойств курсора, метод возвращает значение True, если Провайдер поддерживает это свойство и False в противном случае. Возможные значения параметра являются константами из перечисления CursorOptionEnum. Ряд констант были упомянуты при описании свойств и методов объекта Recordset.Sub Update([Fields], [Values]), Sub UpdateBatch([AffectRecords As AffectEnum = adAffectAll]). Два важных метода, позволяющих проводить обновление отдельной записи или пакета записей в базе данных. Примеры применения метода Update уже приводились.
Содержание раздела