Тверской государственный университет
Опубликован: 13.09.2006 | Доступ: свободный | Студентов: 5132 / 387 | Оценка: 4.23 / 3.83 | Длительность: 28:12:00
Специальности: Программист, Менеджер
Лекция 5:

Объекты ADO

Методы объекта 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 уже приводились.
Ольга Гафарова
Ольга Гафарова

Добрый день. Подскажите формулы при решении задачи на рис. 2.2 в лекции №2. Закон Ома, какие должны использоваться формулы для I и R

Курс: Основы офисного программирования и документы Excel

Серегй Лушников
Серегй Лушников