Обзор возможностей объекта 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 я ограничился печатью количества элементов в этой коллекции, а также имени и значения первого элемента в этой коллекции. Приведу результаты отладочной печати:
'Изменение описания команды 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 я ограничился печатью количества элементов в этой коллекции, а также имени и значения первого элемента в этой коллекции. Приведу результаты отладочной печати:
Заметьте, число параметров в коллекции Parameters равно 2, а не 1, как должно было бы быть. Это связано с моей недоработкой и недоработкой Microsoft. Перед тем, как начать формировать коллекцию Parameters, я должен был очистить ее содержимое, вызвав метод Delete. Я не сделал этого, поскольку метод Delete не вызывается в данном контексте. По этой причине при повторном запуске процедуры произошло добавление параметра к уже имеющейся коллекции. В данном случае, когда выполняется запрос с одним параметром, это не приводит к ошибке, и я не стал усложнять уже и так довольно длинную процедуру. Но в принципе это серьезная ошибка, которая в другой ситуации может привести к неприятностям, например, если бы в следующей команде я попытался бы выполнить другой параметризованный запрос. Так что обратите внимание на эту ситуацию, и корректно работайте с коллекцией Parameters. Заметьте, проблемы исчезают для локально определенного объекта Command .