Лекция № 4. Разработка запросов в приложении Microsoft Access Таблицы базы данных хранят информацию. Но простое хранение информации само по себе бессмысленно. Пользователь должен получать какие-либо сведения из хранимой информации. Просмотр таблиц пользователем для поиска нужных сведений – занятие бесперспективное. В приличной базе данных храниться столько записей, сколько пользователь не может просмотреть за неделю или месяц, а то и за больший период времени. Кроме того, информация разнесена по таблицам, и для ответа на какой-либо вопрос часто необходимы сведения из разных таблиц. Всё это делает необходимым использование автоматизированных средств обработки информации. В базах данных для этих целей применяются запросы. Запросы пишутся на специальном языке SQL (Structured Query Language), с помощью которого можно описать, что вы хотите сделать и какую информацию хотите получить. А СУБД уже применяет определённые механизмы для реализации запроса. В приложении Microsoft Access существует конструктор запросов, который позволяет формировать достаточно сложные запросы, даже не зная языка SQL. Реляционная модель определяет четыре основные операции над базами данных – выборка, обновление, добавление и удаление. Соответственно существуют запросы четырёх типов, предназначенные для выполнения этих операций. Рассмотрим формирования ряда запросов к базе данных, хранящей информацию о недвижимости. Схема данных этой базы представлена на рисунке. 1. Запросы на выборку Запрос на выборку – это простейший и самый распространённый тип запросов, который извлекает подмножество данных из таблицы или нескольких таблиц. Для того чтобы извлекать не все данные, надо указывать условие отбора. 1.1. Запросы к одной таблице Давайте попробуем определить запрос, с помощью которого можно найти здания, построенные более 10 лет назад. Для создания нового запроса необходимо нажать кнопку Конструктор запросов, которая находится в группе Запросы на вкладке Создание. После создания нового запроса появится диалоговое окно, с помощью которого можно добавить таблицы, из которых будут извлекаться данные. В данном случае нам понадобится только одна таблица – Buildings. Далее необходимо выбрать поля, которые будут включены в запрос. Для 19 этого нужно дважды щёлкнуть левой кнопкой мыши по имени поля в таблице. Выберем все поля. Теперь надо сделать самое главное – задать условие отбора. В таблице в нижней части окна конструктора запросов существует одноимённая строка – Условие отбора. В этой строке в поле Year необходимо ввести условие <Year(Date())-10. При первом сохранении запроса приложение Microsoft Access просит ввести имя нового запроса. Для просмотра результатов выполнения запроса необходимо нажать кнопку Выполнить, которая находится в группе Результаты на вкладке Работа с запросами | Конструктор. Теперь мы видим не все записи таблицы Buildings, а только те, которые удовлетворяют условию отбора. В данном запросе мы использовали простейшее условие отбора. Но в реальной жизни обычно условия бывают более сложными, использующими логические операции. Если требуется задать сложное условие для одного поля, то оно записывается с явным использованием логических операций, например, <Year(Date())-10 And >1990. Если же условие отбора включает значения нескольких полей, например, необходимо найти дома, построенные более 10 лет назад, которые при этом изношены более чем на 20%, то эти условия надо записать в столбцы, соответствующие полям, в одной строке. Тогда части условия объединяются логической операцией «И». Если части условия нужно объединить логической операцией «ИЛИ», они записываются в разных строках. 1.2. Запросы к связанным таблицам В предыдущем запросе всё было хорошо, кроме того, что выводились номера улиц вместо их названия. Названия улиц хранятся в другой таблице. Для того чтобы увидеть в одном месте названия улиц и номера домов, необходимо сформировать запрос к нескольким связанным таблицам. К счастью, сделать это совсем несложно. Давайте определим запрос, который выводит информацию о стоимости всех домов на какой-либо улице. Создадим новый запрос и добавим в схему запроса две таблицы – Streets и Buildings. Поскольку в схеме данных уже определена связь между этими таблицами, эта связь отображается и в окне конструктора запроса. Добавим в запрос поля Name и Type из таблицы Streets и поля House и Cost из таблицы Buildings. Если мы сейчас выполним запрос, то увидим список всех домов с названиями улиц, на которых они расположены. Перейдём снова в режим конструктора и добавим условие для названия улицы ="Южная". Теперь при выполнении запроса отображаются только дома, расположенные на Южной улице. Если перейти в режим SQL, можно увидеть запись запроса на языке SQL: SELECT Streets.Name, Streets.Type, Buildings.House, Buildings.Cost FROM Streets INNER JOIN Buildings ON Streets.Street = Buildings.Street WHERE (((Streets.Name)="Южная")); Эта запись указывает СУБД, что нужно объединить таблицы Streets и Buildings в одну, используя связь, заданную в схеме данных, т.е. равенство значений полей Streets.Street и Buildings.Street, и выбрать из объединённой таблицы только те записи, в которых поле Streets.Name имеет значение «Южная». 1.3. Ввод параметра запроса В предыдущем запросе, опять-таки, всё хорошо, кроме того, что он всегда выводит список домов, расположенных на Южной улице. Как быть, если пользователь захочет увидеть сначала список домов, расположенных на одной улице, потом на какой-либо другой улице, потом на третьей? Определять несколько запросов неразумно, тем более, что улиц может быть очень много. Для решения этой проблемы существуют так называемые параметры запроса. Вместо условия можно ввести имя параметра, которое пишется в квадратных скобках и одновременно является текстом, отображаемым в диалоге ввода данных. Теперь перед выполнением запроса СУБД спрашивает название улицы и подставляет в запрос введённое пользователем значение. Кнопка Параметры, которая находится в группе Показать или скрыть на вкладке Работа с запросами | Конструктор, открывает диалог задания типов параметров запроса. Для текстового параметра это неактуально, т.к. можно вводить, что угодно. Но если нужно ввести число, а пользователь вводит не число, выполнение запроса прерывается из-за невозможности сравнивать данных разных типов. Если же указать, что параметр должен быть, например, числом, то при вводе нечислового значения пользователю выдаётся соответствующее предупреждение и организуется повторный ввод данных. 20 В условии отбора можно использовать выражения, включающие параметры запроса. Например, если ввести выражение Like [Название улицы:] & "*", то результатом выполнения запроса будет список всех улиц, начинающихся текстом, введённым пользователем. 1.4. Вычисляемые поля в запросах Ранее мы говорили, что в таблицы базы данных не следует включать вычисляемые поля, чтобы избежать хранения ненужной информации. Однако такие поля бывает желательно отобразить на экране. Запросы предоставляют лёгкий способ решения этой проблемы. В запрос можно вставить вычисляемое поле, т.е. поле, отсутствующее в таблицах, и вычислить значение этого поля на основе значений полей таблиц базы данных с использованием широчайшего набора встроенных функций приложения Microsoft Access. Для создания вычисляемого поля следует задать имя поля и выражение, определяющее вычисления, которые должны быть выполнены приложением Microsoft Access. Для этого в конструкторе запроса в строке Поле надо записать выражение вида ИмяВычисляемогоПоля: Выражение. Модифицируем первый созданный запрос так, чтобы вместо номеров улиц выдавались название и тип улицы, объединённые в одно поле. Для этого в схему запроса надо добавить ещё одну таблицу. Кнопка Отобразить таблицу, которая находится в группе Настройка запроса на вкладке Работа с запросами | Конструктор, открывает диалог добавления таблиц. После этого в свободном столбце в строке Поля нужно написать выражение StreetName: [Streets.Name] & " " & [Streets.Type] для создания вычисляемого поля. Столбец можно перетащить в желаемую позицию. 1.5. Итоговые запросы Все запросы, которые мы создавали до этого момента, имели дело с отдельными записями. Но запросы можно также использовать для получения промежуточных и общих итогов. С их помощью можно вычислить максимальное или минимальное значение некоторого поля, сумму, количество или среднее значение. Итоговый запрос немного отличается от обычного. Каждое поле должно попадать в одну из следующих категорий: поле, используемое в итоговом вычислении, тип нужного вычисления выбирается с помощью строки Групповая операция; поле, используемое для группировки, т.е. все записи, имеющие в этом поле одинаковое значение, объединяются в группу, и в этой группе вычисляется требуемое значение; поле, используемое для отбора, для этого поля задаётся условие отбора, как и в обычном запросе, но поле не должно отображаться на экране. Во всех случаях можно использовать значения не только обычных полей таблицы, но и значения вычисляемых полей. Создадим итоговый запрос, который для каждой улицы вычисляет количество домов, их среднюю стоимость и максимальный износ. Будем учитывать только дома, в которых есть лифт. Создадим новый запрос, добавим нужные таблицы. Далее нужно нажать кнопку Итоги, которая находится в группе Показать или скрыть на вкладке Работа с запросами | Конструктор. Нажатие этой кнопке изменить тип запроса с обычного на итоговый. Добавим вычисляемое поле для названия улицы, а также поля House, Cost, Wear и Elevator. Для поля с названием улицы в строке Групповая операция надо задать значение Группировка, чтобы указать, что значение этого поля используется для группировки записей. Для полей House, Cost и Wear в строке Групповая операция выбираем Count, Avg и Max соответственно. Для поля Elevator в строке Групповая операция выбираем Условие (при этом автоматически снимется флажок Вывод на экран) и в строке Условие отбора вводим значение Истина (можно ввести число 1, которое автоматически преобразуется в нужное логическое значение). Теперь можно выполнить запрос. 2. Запросы на обновление Запрос на обновление находит записи, удовлетворяющие некоторому условию, и изменяет их. Можно корректировать столько полей записи, сколько нужно. В изменяемое поле можно внести совершенного новое значение, а можно вычислить новое значение на основе старого. Создадим запрос, изменяющий износ зданий. Будем считать, что здания, построенные меньше 20 лет назад, изнашиваются на 2% в год. Будьте внимательны! Если вы будете 21 выполнять этот запрос каждый день, то очень скоро данные перестанут соответствовать действительности. Вообще, все запросы, изменяющие информацию (запросы на обновление, на добавление и на удаление), надо использовать с осторожностью. Новый запрос создаётся как обычно. Также добавляются таблицы в схему запроса. Далее надо изменить тип запроса. Для этого надо нажать кнопку Обновление, которая находится в группе Тип запроса на вкладке Работа с запросами | Конструктор. Поле для конструирования запроса слегка изменилось. Добавим в запрос поля Wear и Year. Для поля Wear в строке Обновление надо задать выражение [Wear]+2, а для поля Year в строке Условие отбора – выражение >Year(Date())-20. Если перейти в режим таблицы, можно увидеть значения, которые будут модифицированы. При выполнении запроса износ все зданий, удовлетворяющих условию, увеличится на 2. К сожалению, язык SQL не является процедурным языком и не поддерживает конструкцию «иначе». Поэтому износ всех остальных зданий останется без изменения. Для изменения износа зданий, построенных более 20 лет назад, надо писать отдельный запрос. 3. Запросы на добавление Запрос на добавление выбирает записи из одной таблицы и вставляет их в другую таблицу. Такие запросы имеют смысл, если у вас есть повторяющиеся таблицы в разных базах данных или если все новые записи добавляются сначала в промежуточную таблицу, которая должна пройти дополнительную проверку. После проверки можно автоматически добавить записи в основную таблицу. При переносе данных нужно быть уверенным в полной согласованности таблиц. Типы данных вставляемых и заменяемых полей должны быть совместимыми. СУБД применяет все обычные проверки при вставке, т.е. в любом случае нельзя вставить повторяющие данные в те поля, где это запрещено, нельзя обойти условия на значения полей и т.д. Для создания запроса на добавление нужно создать запрос, вставить таблицы, из которых будут выбираться данные, и изменить тип запроса с помощью кнопки Добавление, которая находится в группе Тип запроса на вкладке Работа с запросами | Конструктор. После этого приложение Microsoft Access спросит, в какую таблицу следует добавлять данные. Затем можно будет определить соответствие поле таблицы-источника и таблицы-преемника. 4. Запросы на удаление Запрос на удаление – самый опасный тип запросов. При неверном задании условий отбора можно удалить лишние записи, и даже все записи таблицы. К сожалению, в таких случаях невозможно использовать кнопку «Отменить». Для создания запроса на удаление нужно создать запрос, вставить таблицы, из которых будут удаляться данные, и изменить тип запроса с помощью кнопки Удаление, которая находится в группе Тип запроса на вкладке Работа с запросами | Конструктор. После этого нужно выбрать поля, по значению которых будут отбираться записи для удаления, и задать условие отбора. Желательно также дважды щёлкнуть левой кнопкой мыши по звёздочки в таблице – в запрос будет вставлено специальное поле со значением Из в строке Удаление. Это поле позволит просмотреть записи, отобранные на удаление, в режиме таблицы. После того, как вы убедитесь, что отобраны только нужные записи, можно выполнить запрос на удаление. 22