Непонятен ход решения задачи |
Объекты ADO
Свойства объекта Command
У объекта Command 9 свойств, из которых 7 - терминальные, а два свойства возвращают коллекции Parameters и Propertiies, что отображено на рис.5.1. Давайте рассмотрим описание всех свойств этого объекта:
-
Property ActiveConnection As Connection. Заметьте, я был не точен, когда говорил, что только два свойства объекта Command возвращают объекты в качестве результата. Свойство ActiveConnection при открытом соединении также возвращает объект Connection, задающий соединение, связанное с командой. Наличие этого свойства отражает связи между объектами. Нельзя выполнить команду, если не установлено соединение. Свойство позволяет получить доступ к объекту Connection, задающему соединение. Здесь есть, однако, некоторая тонкость, из-за которой это свойство имеет двойственную природу. Дело в том, что при закрытом соединении вернуть ссылку на объект невозможно и потому возвращается строка, содержащая описание соединения.
Свойством ActiveConnection обладают и другие объекты - Recordset и Record.
Заметьте, следует корректно установить значение этого свойства - на открытый объект Connection или на корректно определенную строку, задающую соединение, еще до того, как будет выполняться метод Execute объекта Command, в противном случае возникнет ошибка.
Если между двумя выполнениями команды следует изменить соединение, то вначале необходимо свойству ActiveConnection присвоить значение Nothing, в результате Провайдер освободит ресурсы и корректно произведет операцию отсоединения. После чего можно установить новое соединение. Лишь некоторые Провайдеры позволяют проводить изменения в соединении без промежуточного присваивания значения Nothing.
Изменение соединения оставляет нетронутой коллекцию Parameters, если она заполнялась вручную, значения, устанавливаемые Провайдером, при этом очищаются.
При закрытии соединения, связанного с командой, значение свойства устанавливается в Nothing. Попытка связать команду с закрытым соединением приводит к ошибке. -
Property CommandText As String. Устанавливает или возвращает строку, текст которой содержит описание команды для Провайдера. Чаще всего, этот текст содержит описание SQL-оператора, но может быть именем таблицы, относительным URL-адресом или вызовом хранимой процедуры.
Если свойство Prepered установлено как True и объект Command связан с открытым соединением, то Провайдер транслирует текст команды в исполняемый запрос и сохраняет его в таком виде. Это повышает общую эффективность выполнения при многократных вызовах команды.
В зависимости от значения свойства CommandType возможно изменение значения свойства CommandText, чтобы привести его в соответствие со спецификой Провайдера.
Когда необходимо в команде задать ресурс, такой как файл или каталог, то в свойстве CommandText задается URL-адрес ресурса. URL-адрес, использующий http-схему, приводит к автоматическому вызову специального Провайдера - OLE DB Provider for Internet Publishing. - Property CommandStream As Stream. Это свойство появилось в последней на момент написания данного текста версии ADO 2.6. Свойства CommandStream и CommandText является взаимоисключающими. Когда устанавливается свойство CommandStream, то свойство CommandText автоматически становится равным пустой строке. Эти два свойства задают альтернативные способы задания описания команды. Свойство CommandText задает описание строкой. Свойство CommandStream устанавливает или возвращает поток, используемый как ввод для объекта Command. Формат потока определяется спецификой Провайдера.
- Property Dialect As String. Свойство определено в версии ADO 2.6. Оно задает диалект - синтаксис и систему правил, которыми руководствуется Провайдер при разборе входной строки или потока, заданного свойствами CommandText и CommandStream. Свойство содержит GUID, который и задает диалект, используемый Провайдером.
- Property CommandTimeout As Long. Смысл этого свойства я описывал ранее при рассмотрении объекта Connection. Напомню, значение свойства задает время, в течение которого команда должна быть выполнена. При превышении времени возникнет ошибка.
- Property CommandType As CommandTypeEnum. Свойство позволяет установить или определить тип объекта Command, который может быть одним из предустановленных перечислением значений. Тип можно и не устанавливать, - значение свойства по умолчанию - adCmdUnknown. Другие возможные значения типа - adCmdFile, adCmdStoredProc, adCmdTable, adCmdTableDirect, adCmdText. Корректное указание типа повышает эффективность исполнения команды, позволяя Провайдеру не выполнять лишней работы по установлению типа. Вместе с тем неверное указание типа будет приводить к появлению ошибки при вызове метода Execute.
- Property Name As String. Возвращает или устанавливает имя команды. Я уже говорил о способе использования этого свойства и демонстрировал схему его применения при описании объекта Connection. Далее я расскажу о том, что мои попытки задать имя команде потерпели неудачу при работе с Провайдером, обеспечивающим работу с базой данных Access.
- Property Parameters As Parameters. Является одним из двух свойств-участников объекта Command. В качестве результата возвращает коллекцию параметров, передаваемых Провайдеру, когда команда задает запрос с параметрами или представляет вызов хранимой процедуры, у которой есть параметры. Это свойство является свойством объекта по умолчанию, что, напомню, означает возможность опускать имя свойства при его вызове, так что записи MyCmd.Parameters(i) и MyCmd(i) эквивалентны. Позже я еще буду рассматривать объекты Parameters и Parameter.
- Property NamedParameters As Boolean. Это булево свойство определено, начиная с версии ADO 2.6. Когда оно имеет значение True, то имена параметров передаются Провайдеру и могут быть использованы при вызовах команды, требующей передачи параметров. При значении False порядок передачи параметров жестко фиксирован.
- Property Prepared As Boolean. Булево свойство, имеет статус "чтение/запись". Я уже говорил, что установка значения True повышает эффективность исполнения команды при многократных вызовах, за счет того, что Провайдер единожды выполняет подготовительную работу и затем хранит скомпилированную версию команды. Не все Провайдеры поддерживают это свойство.
- Property Properties As Properties. Еще одно свойство, возвращающее коллекцию объектов. Каждый элемент этой коллекции - объект Property - задает одну из характеристик объекта Command, передаваемых Провайдеру. Этих характеристик, зависящих от Провайдера и объекта довольно много. Вспомните, в предыдущем примере, когда печатались свойства объекта Connection, его коллекция Properties насчитывала 94 элемента.
- Property State As Long. Я уже рассказывал об этом свойстве, которым обладают многие объекты ADO, и приводил пример работы с ним.
Методы объекта Command
У объекта Command всего три метода. Рассмотрим их:
-
Function Execute([RecordsAffected], [Parameters], [Options As Long = -1]) As Recordset. Запускает на выполнение команду, предписанную свойствами CommandText или CommandStream. В качестве результата возвращает либо ссылку на объект Recordset, либо поток, либо Nothing.
Параметры метода имеют следующий смысл:
- RecordsAffected - переменная типа Long, возвращающая число записей, затронутых при выполнении операции. Этот параметр не дает числа записей результата. Для этого необходимо использовать свойство RecordCount.
- Parameters - массив значений параметров типа Variant. Этот аргумент позволяет переопределить все или некоторые из параметров, заданных свойством Parameters объекта Command.
- Options - значение, указывающее, как Провайдер должен транслировать текст входной строки или потока. Может быть битовой маской одного или более значений из перечислений CommandTypeEnum или ExecuteOptionEnum. Так, если результатом выполнения команды должен быть поток, то значение этого свойства следует задать как adExecuteStream.
- Sub Cancel(). Прерывает выполнение команды Execute. Подробности уже рассматривались при описании объекта Connection.
-
Function CreateParameter([Name As String], [Type As DataTypeEnum = adEmpty], [Direction As ParameterDirectionEnum = adParamInput], [Size As Long], [Value]) As Parameter. Позволяет создать новый объект Parameter с заданными свойствами. Ссылка на этот объект и является возвращаемым значением. Параметры метода имеют следующий смысл:
- Name - имя параметра,
- Type -тип данных объекта Parameter, заданный перечислением DataTypeEnum. Вот лишь некоторые из возможных значений: adArray, adChar, adDate, adCurrency, adIUnknown.
- Direction - тип самого объекта Parameter, заданный перечислением ParameterDirectionEnum. Он определяет является ли параметром входным или выходным параметром запроса или процедуры, возвращаемым значением хранимой процедуры Вот его возможные значения: adParamInput, adParamInputOutput, adParamOutput, adParamReturnValue, adParamUnknown.
- Size - значение указывающее максимальную длину значения параметра в символах или байтах.
- Value - значение типа Variant, указывающее значение объекта Parameter.
Обзор возможностей объекта Command и примеры применения
Подведу теперь некоторые итоги и укажу на те возможности, которые предоставляет объекта Command:
- Задать описание команды, используя свойства CommandText и CommandStream. Второе из этих свойств позволяет, например, задавать XML-запросы.
- Связать объект Command с открытым соединением, используя свойство ActiveConnection.
- Вызывать команду на исполнение, используя метод Execute объекта Command, или для именованного объекта вызывать команду как метод объекта Connection.
- Формировать объект Recordset как результат выполнения команды.
- В момент вызова команды передавать параметры хранимой процедуре или параметризованному запросу.
- Формировать при необходимости объекты Parameter и создавать коллекцию Parameters.
- Повышать эффективность выполнения команды, используя свойства Prepared и CommandType.
Приведу пример создания и работы с объектом Command:
Public Sub CreateCommands() 'Создание команд, выполняющих операции 'с тестовой базой данных Access Dim Par1 As Object Dim strSQL1 As String, strSQL2 As String Dim strSQL3 As String, strSQL4 As String Dim KeyAuthor As String, KeyName As String Const Кавычка = "'" KeyAuthor = "Б. Гейтс": KeyName = "Дорога в будущее" 'Задание четырех SQL операторов strSQL1 = "Select * FROM [Книги]WHERE [Автор]= " _ & Кавычка & KeyAuthor & Кавычка strSQL2 = "Select * FROM [Книги]WHERE ([Название]=" _ & Кавычка & KeyName & Кавычка & " AND [Автор] = " _ & Кавычка & KeyAuthor & Кавычка & ")" strSQL3 = "Select * FROM [Заказчики в Твери]" strSQL4 = "Select * FROM [зак-из-гор]" 'задание свойств объекта Command Cmd1.ActiveConnection = Con1 Cmd1.CommandText = strSQL1 Cmd1.CommandType = adCmdText Cmd1.Prepared = True 'Cmd1.Name = "AuthorAndBook" 'вызов команды на исполнение методом Execute Set Rst1 = Cmd1.Execute 'печать результата Rst1.MoveFirst Debug.Print Rst1!Автор Debug.Print Rst1!Название Debug.Print Rst1!Цена Rst1.MoveLast Debug.Print Rst1!Автор Debug.Print Rst1!Название Debug.Print Rst1!Цена 'Изменение описания команды Cmd1.CommandText = strSQL2 Set Rst1 = Cmd1.Execute 'печать результата Debug.Print Rst1!Автор Debug.Print Rst1!Название Debug.Print Rst1!Цена 'Вызов хранимого запроса базы данных Cmd1.CommandText = strSQL3 Set Rst1 = Cmd1.Execute 'печать результата Rst1.MoveFirst Debug.Print Rst1!Название Rst1.MoveLast Debug.Print Rst1!Название 'Вызов хранимого запроса с параметрами Cmd1.CommandText = strSQL4 Set Par1 = Cmd1.CreateParameter("Town", adBSTR, adParamInput) Cmd1.Parameters.Append Par1 Par1.Value = "Тверь" Set Rst1 = Cmd1.Execute 'печать результата Rst1.MoveFirst Debug.Print Rst1!Название Rst1.MoveLast Debug.Print Rst1!Название 'печать характеристик Cmd1 Debug.Print "ActiveConnection = ", Cmd1.ActiveConnection Debug.Print "CommandTimeout = ", Cmd1.CommandTimeout Debug.Print "CommandType = ", Cmd1.CommandType Debug.Print "Name = ", Cmd1.Name Debug.Print "CommandText = ", Cmd1.CommandText Debug.Print "Prepared = ", Cmd1.Prepared Debug.Print "Parameters.Count = ", Cmd1.Parameters.Count Debug.Print "Properies.Count = ", Cmd1.Properties.Count Debug.Print "State = ", Cmd1.State Debug.Print "Properties(1).Name = ", Cmd1.Properties(1).Name Debug.Print "Properties(1).Value = ", Cmd1.Properties(1).Value End Sub
Прокомментирую текст этой процедуры:
- Я выполняю четыре разные команды над базой данных. Описание этих команд я задал в четырех SQL-операторах. Первый из них выбирает из таблицы "Книги" все книги, автор которых задан переменной KeyAuthor, имеющей в данном примере значение "Б. Гейтс". Замечу, что в таблице хранятся сведения о двух книгах этого автора. Во втором операторе запрос уточняется и ищется книга с фиксированным названием. Третий SQL-оператор обращается к стандартному запросу, хранимому в базе данных. Этот запрос выдает в качестве результата набор записей, содержащих заказчиков из города Тверь. Наконец, текст четвертой команды представляет вызов параметризованного запроса, где ищутся заказчики из города, название которого является параметром запроса.
- Прежде чем вызвать первую команду на исполнение, я формирую свойства объекта Command. Первым делом формирую свойство CommandText, задающее описание команды, но не только его. Я задал свойство ActiveConnection, что совершенно необходимо, а, кроме того, задал свойства Prepared и CommandType. Заметьте, в данном контексте невозможно именовать команду, поэтому мне пришлось закомментировать назначение этого свойства, чтобы избежать появления ошибки.
- Последовательно изменяя описание команды - свойство CommandText, - я выполнил все четыре команды. Конечно же, прежде чем выполнить четвертую команду, требующую задания параметра в момент ее выполнения, мне пришлось этот параметр создать. Для его создания я вызвал метод CreateParameter и созданный таким образом параметр присоединил к коллекции Parameters. Хочу обратить внимание на одну деталь, переменную Par1 мне пришлось описать как имеющую класс Object, а не класс Parameter, иначе возникало несоответствие типов при попытке присвоения ей ссылки на объект, созданный в результате выполнения метода CreateParameter.
- Для демонстрации корректности выполнения команд, я печатаю значения записей из набора Rst1, создаваемого при выполнении очередной команды. Заметьте, я использую некоторые операции над объектом Recordset - MoveFirst и MoveLast, позволяющие выбрать нужную запись в наборе. Чуть позже я подробно рассмотрю все свойства и методы этого объекта.
- В заключение, я печатаю некоторые свойства объекта Command. Из большой коллекции Properties я ограничился печатью количества элементов в этой коллекции, а также имени и значения первого элемента в этой коллекции. Приведу результаты отладочной печати:
Б. Гейтс Дорога в будущее 23 Б. Гейтс Бизнес со скоростью мысли 150 Б. Гейтс Дорога в будущее 23 Книжная лавка ООО 'Тверькнига' Книжная лавка ООО 'Тверькнига' ActiveConnection = Provider=Microsoft.Jet.OLEDB.4.0;Password="";User ID=Admin;Data Source=c:\!O2000\DsCd\Ch14\dbPP2000.mdb;Mode=Share Deny None;Extended Properties="";Jet OLEDB:System database="";Jet OLEDB:Registry Path="";Jet OLEDB:Database Password="";Jet OLEDB:Engine Type=5;Jet OLEDB:Database Locking Mode=1;Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password="";Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;Jet OLEDB:Don't Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;Jet OLEDB:SFP=False CommandTimeout = 30 CommandType = 1 Name = CommandText = Select * FROM [зак-из-гор] Prepared = True Parameters.Count = 2 Properies.Count = 88 State = 0 Properties(1).Name = Blocking Storage Objects Properties(1).Value = True