Стив Каммингс - VBA для чайников
Конструктор запросов Access замечательно справляется с поставленными задачами, но он не может обработать все встречающиеся ситуации. Он не позволяет создавать запросы сложных типов, т.е. подзапросы. Конечно же, его хранимые процедуры работают только с базами данных Jet (однако другие базы данных содержат подобные средства визуального конструирования запросов). Вы можете попробовать конструктор запросов
Access для получения SQL-кода для баз данных другого типа, однако не забывайте о том, что разные базы данных используют разные версии SQL, поэтому вам придется вносить коррективы в полученный код.
Знакомство с диалектами SQL
Хотя SQL и считается практически универсальным языком создания запросов для систем управления базами данных, многие базы данных понимают только определенные диалекты
SQL. Jet, например, предлагает несколько нестандартных усовершенствований SQL, но не реализует некоторые функции, присутствующие в стандартной версии SQL. В настоящей главе я ограничусь рассмотрением Jet-версии SQL, поскольку именно с ней сможет работать каждый пользователь Office. Если вы используете другую систему управления базами данных, нам придется подгонять изложенные мною сведения под доступный вам диалект SQL.
Вставка инструкций SQL в VBA-код
Фрагменты кола, приведенные раньше в настоящей главе, должны были проиллюстрировать, как добавлять инструкции SQL в код, написанный на VBA. Здесь очень важно не забывать о том, что VBA обрабатывает инструкции SQL как текстовые строки, а не как часть собственно программного кода. Эти строки претерпевают специальную обработку, когда интерпретируются как аргументы методов Open или Execute объектов ADO, но до тех пор они остаются обычными строками VBA, содержащими текст.
По этой причине вам следует заключать каждую инструкцию SQL в двойные кавычки.
Независимо от того, настраиваете вы свойство CommandText объекта Command или указываете аргумент метода Open объекта Recordset, использование двойных кавычек обязательно. И опять, вы найдете много примеров в предыдущих разделах настоящей главы. И не пропустите материал раздела "Настройка набора записей: задаем критерии" дальше в настоящей главе.
Написание инструкций SELECT
Процесс создания объектов Recordset модели ADO я подробно рассмотрел раньше в настоящей главе. В этом разделе основной акцент будет сделан именно на коде SQL, необходимом для определения того, какие записи относятся к набору. Вам необходимо выполнить подобную задачу как можно точнее, поэтому инструкция SELECT - это именно то, что вам нужно.
Простейшая форма инструкции SELECT получает все записи из одной таблицы. Приведенный ниже пример возвращает все поля и все записи из таблицы Toys:
SELECT * FROM Toys
Поскольку эта инструкция не содержит никаких дополнительных критериев, в возвращаемый в результате выполнения инструкции набор записей включаются все записи из таблицы Toys. Звездочка означает, что набор записей, помимо всего прочего, содержит еще и все поля из таблицы.
Инструкции SELECT извлекают записи из базы данных, но не изменяют при этом хранящиеся там данные. Для внесения подобных изменений вы должны изменить значения полей в наборе записей, после чего использовать такие инструкции SQL, как UPDATE или DELETE.
Связывание нескольких таблиц в инструкциях SELECT
Одна инструкция SELECT может работать с более чем одной таблицей. Просто перечисsiire ULC необходимые таблицы, с которыми должна работать инструкция, как показано ниже:
SELECT * FROM Toys, Clerks
Однако набор записей, полученный в результате подобного перечисления таблицы, оказывается не таким уж полезным. Ничто не связывает эти таблицы, поэтому база данных не знает, какая запись из первой таблицы соответствует какой записи из второй таблицы. Получается, что каждой записи из первой таблицы соответствуют все записи из второй.
Для того чтобы правильно связать две таблицы, выполните в инструкции SELECT соединение. Внутреннее соединение, наиболее распространенное, создает запись в наборе, базируясь на соответствии записей в исходных таблицах, а соответствие базируется на одинаковых значениях определенных полей таблиц. Например, приведенная ниже инструкция создает набор записей, в котором перечисляются запасные компоненты для каждой игрушки в списке:
SELECT Toy, Rep FROM Toys INNER JOIN Reps On Toys.ID =
Reps.ToyID
Для создания внутреннего соединения разместите конструкцию INNER JOIN между именами таблиц в инструкции FROM. После этого укажите ключевое слово ON, которое определяет поля, содержащие сравниваемые значения. Обычно имена полей после ключевого слова ON разделяются знаком равенства, что свидетельствует о том, что для выбранных записей значения, содержащиеся в указанных полях, должны совпадать (допускается использование и других операторов сравнения).
Выбор полей
Для указания набора полей укажите их имена явным образом, как показано ниже:
SELECT Toy, InStock, OnOrder FROM ToyInventory
Если имя поля содержит пробелы или знаки пунктуации, заключите его в квадратные скобки, как показано ниже:
SELECT Toy, [ List Price ], [Sale Price] FROM ToyInventory
По умолчанию значение свойства Name каждого объекта Field в наборе записей, полученном с помощью инструкции SELECT, равно имени соответствующего поля в исходной таблице. Вы можете назначить другие имена полей (псевдонимы) в наборе записей, используя ключевое слово AS для каждого поля, которое вы решили переименовать:
SELECT Toy AS ToyName, InStock AS OnHand, OnOrder FROM ToyInventory
Если вы извлекаете записи из нескольких таблиц и хотите выбрать поля с одинаковыми именами, укажите перед именем поля имя соответствующей таблицы. Вот соответствующий пример:
SELECT ToyInventory.Name, Clerks.Name FROM ToyInventory, Clerks
Вы можете построить набор записей, который будет содержать новые поля, а их значения вычисляются на базе значений, содержащихся в базе данных. В инструкции SELECT подобные поля определяются с помощью выражений, базирующихся на операторах и функциях
VBA. Например, предположим, что вам необходимо перечислить цены на товары, которые получатся после снижения на 10%:
SELECT Toy, ( Price * .9) AS SalePrice FROM ToyInventory
Обратите внимание на то, что при определении вычисляемого поля вы должны включить ключевое слово для создания псевдонима (имени) поля в наборе записей. Скобки необязательны, однако они помогают подчеркнуть выражение, которое необходимо вычислять.
В выражении, позволяющем получить значение нового поля, допускается использование нескольких полей, например, так: ( Price * InStock) AS InventoryValue.
В качестве еще одного примера предположим, что по какой-то причине вам необходимо получить набор записей, в котором будут перечислены имена всех клерков прописными буквами, но при этом способ представления имен в самой базе данных не должен изменяться.
Это позволяет сделать приведенная ниже инструкция:
SELECT UCase(Name) AS [ Clerk's name] FROM Clerks
При использовании обобщенных функций SQL инструкция SELECT позволяет получить набор записей, который будет содержать только одно результирующее значение, например, количество записей, содержащих заданное значение в определенном поле:
SELECT Count (Recyclable) AS [Can Recycle] From Toys или среднее значение всех полей:
SELECT Avg(Price) AS [Average Price] FROM Toys
После этого вы можете передать значение поля этой записи переменной в вашем коде VBA для использования в вычислениях или отображения в форме: intRecyclabl eCount = rstRecyclabl eToys![ Canrecycle]
К обобщенным функциям относятся следующие: Count, Avg, Sum, Min, Max, а также несколько статистических функций.
Используйте предикаты DISTINCT, DISTINCTROW и ТОР в инструкции SELECT в качестве простых инструментов получения определенных наборов записей из баз данных. Эти специальные слова необходимо указывать сразу после инструкции SELECT, как показано в табл. 17.3.
Таблица 17.3. Предикаты SQL для выбора записей
Предикат
Использование
Пример
DISTINCT
Выбирает только одну запись, если база данных содержит несколько записей с идентичными данными в указанных полях
SELECT DISTINCT Address FROM Members
Возвращает набор записей, содержащий только одну запись для каждого адреса, даже если в таблице Member s содержится по несколько записей для каждого адреса
DISTINCT ROW
Выбирает все уникальные записи, базируясь на значениях всех полей. Если две записи отличаются всего одним символом, они все равно будут включены в набор; если они полностью идентичны, в набор будет включена только одна из них
SELECT DISTINCTROW Name, Address FROM Members
Возвращает набор записей, содержащий записи с полями Name и Address, Набор может содержать дублирующиеся записи, но только в том случае, если отличаются значения других полей
ТОР л
Выбирает указанное число записей в верхней или нижней части определяемого ключевым словом ORDER BY
SELECT TOP 10 ToyName FROM Toys ORDER BY Units Sold
Возвращает набор записей, содержащий сведения о 10 диапазона, лучше всего продаваемых игрушках. Для определений 10 хуже всего продаваемых игрушек вам следует добавить ключевое слово ASC (ascending - no убыванию) после слова Units Sold