«fc
3-е издание
Джеффри П. Мак-Манус Джеки Голдштейн Кевин Т. Прайс
Обработка баз данных на Visual Basic* .NET 3-е издание
Database Access with Visual Basic«.NET Third Edition
Jeffrey P. McManus Jackie Goldstein Kevin T. Price
^ Addison-Wesley Boston * San Francisco 4 New York * Toronto * Montreal London * Munich * Paris * Madrid Capetown * Sydney * Tokyo * Singapore * Mexico City
Database Access with Visual Basic«.NET Third Edition
Jeffrey P. McManus Jackie Goldstein Kevin T. Price
Addison-Wesley Boston * San Francisco Ф New York 4 Toronto 4 Montreal London * Munich 4 Paris * Madrid Capetown * Sydney 4 Tokyo * Singapore * Mexico City
Обработка баз данных на Visual Basic* .NET 3-е издание
Обработка баз данных на Visual Basic® .NET 3-е издание
Джеффри П. Мак-Манус Джеки Голдштейн Кевин Т. Прайс
Издательский дом "Вильяме" Москва * Санкт-Петербург 4 Киев 2003
ББК 32.973.26-018.2.75 М15 УДК 681.3.07 Издательский дом "Вильяме" Зав. редакцией С.Н. Тригуб Руководитель проекта В.В. Александров Перевод с английского канд. физ.-мат. наук Ю.Г. Гордиенко Под редакцией канд. физ.-мат. наук Ю.Г. Гордиенко, В.В. Александрова По общим вопросам обращайтесь в Издательский дом "Вильяме" по адресу:
[email protected], http://wwTV.williamspublishing.com Мак-Манус, Джеффри, П., Голдштейн, Джеки, Прайс, Кевин, Т. М15
Обработка баз данных на Visual Basic .NET, 3-е издание.: Пер. с англ. — М.: Издательский дом "Вильяме", 2003. — 416 с.: ил. — Парал. тит. англ. ISBN 5-8459-0512-5 (рус.) Это практическое руководство разработчика программного обеспечения на Visual Basic .NET и ADO.NET, предназначенное для создания приложений баз данных на основе WinForms, Web-форм и Web-служб. В книге описываются практические способы решения задач доступа к данным, с которыми сталкиваются разработчики на Visual Basic .NET в своей повседневной деятельности. Книга начинается с основных сведений о создании баз данных, использовании языка структурированных запросов SQL и системы управления базами данных Microsoft SQL Server 2000. Затем рассматриваются способы использования основных объектов модели ADO.NET для доступа к данным в реляционных базах данных. Благодаря подробным примерам, читатели могут изучить способы использования основных свойств и методов, а также узнать о более сложных компонентах и технологиях. Многочисленные листинги с кодом на языке Visual Basic .NET иллюстрируют используемые концепции, а бизнес-ситуации показывают практическую область их применения. ББК 32.973.26-018.2.75
Все названия программных продуктов являются зарегистрированными торговыми марками соответствующих фирм. Никакая часть настоящего издания ни в каких целях не может быть воспроизведена в какой бы то ни было форме и какими бы то ни было средствами, будь то электронные или механические, включая фотокопирование и запись на магнитный носитель, если на это нет письменного разрешения издательства Addison-Wesley Publishing Company, Inc. Authorized translation from the English language edition published by Pearson Esucation, Inc., Copyright © 2003 All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from the Publisher. Russian language edition published by Williams Publishing House according to the Agreement with R&I Enterprises International, Copyright © 2003
ISBN 5-8459-0512-5 (рус.) ISBN 0-672-32343-5 (англ.)
© Издательский дом "Вильяме", 2003 © Pearson Esucation, Inc., 2003
Оглавление Предисловие
12
ГЛАВА 1. Основы построения баз данных
19
ГЛАВА 2. Запросы и команды на языке SQL
65
ГЛАВА 3. Знакомство с SQL Server 2000
97
ГЛАВА 4. Модель ADO.NET: провайдеры данных
163
ГЛАВА 5. ADO.NET: объект DataSet
199
ГЛАВА 6. ADO.NET: объект DataAdapter
231
ГЛАВА 7. ADO.NET: дополнительные компоненты
261
ГЛАВА 8. Работа с проектом базы данных в среде Visual Studio .NET
287
ГЛАВА 9. XML и .NET
307
ГЛАВА 10. ADO.NET и XML
329
ГЛАВА 11. Web-формы: приложения на основе ASP.NET для работы с базами данных
367
ГЛАВА 12. Web-службы и технологии промежуточного уровня
387
Содержание
Содержание Предисловие
12
Для кого предназначена эта книга Структура книги Используемое программное обеспечение Об авторах О соавторе О рецензентах Благодарности
12 13 13 16 16 17 18
ГЛАВА 1. Основы построения баз данных
19
Что представляет собой база данных Что такое платформа базы данных Бизнес-ситуации Бизнес-ситуация 1.1: основные сведения о компании Jones Novelties Incorporated Таблицы и поля Манипулирование данными с помощью объектов Типы данных Схема базы данных Использование инструментов Visual Studio для создания базы данных Определение индексов и первичного ключа Создание схемы базы данных Использование программы Microsoft Visio для просмотра и изменения схемы базы данных Отношения Использование ссылочной целостности для поддержания непротиворечивости данных Проверка ограничений ссылочной целостности с помощью Server Explorer Каскадные обновления и каскадные удаления Нормализация Отношения типа один-к-одному Отношения типа один-ко-многим Отношения типа многие-ко-многим Создание пользовательского интерфейса на основе Windows Forms Подключение к базе данных и работа с записями Создание приложения для просмотра данных Программный способ связывания данных Элементы управления, взаимодействующие с данными Обновление записей в приложении просмотра данных
20 21 21 21 22 26 27 28 28 31 33 37 43 45 46 47 48 51 51 52 52 53 54 57 58 58
Содержание
Создание новых записей в форме, связанной с данными Удаление записей из связанной с данными формы Проверка введенных данных в форме, связанной с данными Резюме Вопросы и ответы
60 61 61 63 63
ГЛАВА 2. Запросы и команды на языке SQL
65
Что такое запрос Тестирование запросов с помощью компонента Server Explorer Отбор записей с помощью предложения SELECT Указание источника записей с помощью предложения FROM Формирование критериев с использованием предложения WHERE Операторы, используемые в предложении WHERE Сортировка результатов с помощью предложения ORDER BY Сортировка в убывающей последовательности Сортировка по нескольким полям Отображение первых или последних записей диапазона с помощью предложения ТОР Создание запросов TOP PERCENT Объединение связанных таблиц в запросе Выражение объединения в SQL Использование конструктора представлений для создания объединений Использование внешних объединений Выполнение вычислений в запросах Определение псевдонимов с использованием предложения AS Запросы, которые группируют данные и подводят итоги Применение предложения HAVING для группирования данных в запросах Функция SUM Перечень итоговых функций Запросы на объединение Подзапросы Манипулирование данными с помощью SQL Запросы на обновление Запросы на удаление Запрос на добавление записей Запросы на основе команды SELECT INTO Использование языка определения данных Создание элементов базы данных с помощью предложения CREATE Добавление ограничений в таблицу Назначение внешнего ключа Создание индексов с помощью команды CREATE INDEX Удаление таблиц и индексов с помощью предложения DROP Модификация структуры таблицы с помощью предложения ALTER Резюме Вопросы и ответы
66 67 69 70 71 72 74 74 75 75 76 77 78 78 79 81 82 83 84 85 86 87 88 88 89 90 90 91 92 92 93 94 94 95 95 96 96
Содержание
ГЛАВА 3. Знакомство с SQL Server 2000
97
Установка и запуск Microsoft SQL Server Требования для инсталляции SQL Server 2000 Установка SQL Server 2000 Запуск и остановка SQL Server Управление способом запуска SQL Server Основы работы с SQL Server 2000 Запуск программы SQL Server Enterprise Manager Создание базы данных с помощью программы SQL Server Enterprise Manager Создание таблиц в базе данных SQL Server Использование программы SQL Query Analyzer для доступа к базе данных Использование представлений для управления доступом к данным Создание и запуск хранимых процедур Отображение текста существующих представлений или хранимых процедур Создание триггеров Бизнес-ситуация 3.1: создание триггера для поиска созвучных слов Управление пользователями и средства безопасности с помощью программы SQL Server Enterprise Manager Применение ограничений безопасности в программе SQL Query Analyzer Определение подключенных пользователей Удаление объектов базы данных Бизнес-ситуация 3.2: SQL-сценарий для создания базы данных Резюме Вопросы и ответы
99 101 102 104 105 105 106 108 110 116 121 126 130 131 132
ГЛАВА 4. Модель ADO.NET: провайдеры данных Обзор технологии ADO.NET Мотивация и философия ADO.NET и ADO 2-Х Место ADO.NET в архитектуре .NET Framework Прикладные интерфейсы Провайдеры данных ADO.NET Провайдер данных SqlClient Провайдер данных Oledb Провайдер данных Odbc Основные объекты Объект Connection Объект Command Применение объекта Command с параметрами и хранимыми процедурами Выполнение команд Объект DataReader Использование объектов Connection и Command во время создания приложения Другие провайдеры данных Бизнес-ситуация 4.1: создание процедуры для архивирования старых заказов по годам
134 141 143 144 144 161 161
163 164 164 166 166 167 167 168 168 168 169 170 173 176 179 186 189 190 191
Содержание
Резюме Вопросы и ответы
196 197
ГЛАВА 5. ADO.NET: объект DataSet
199
Компоненты объекта DataSet Ввод данных в объект DataSet Определение схемы объекта DataTable Вставка данных в объект DataTable Обновление данных в объекте DataSet Доступ к данным с помощью объекта DataTable Применение объекта DataSet Резюме Вопросы и ответы
200 202 202 206 207 211 223 229 229
ГЛАВА 6. ADO.NET: объект DataAdapter Передача данных из источника данных в объект DataSet Обновление источника данных Указание команд обновления Резюме Вопросы и ответы
ГЛАВА 7. ADO.NET: дополнительные компоненты Обнаружение конфликтов при параллельном доступе к данным Отображения таблиц и полей Объект DataView Бизнес-ситуация 7.1: просмотр данных из разных источников Строго типизированные наборы данных Резюме Вопросы и ответы
ГЛАВА 8. Работа с проектом базы данных в среде Visual Studio .NET
231 233 238 240 259 259
261 262 266 268 275 280 285 285
287
Создание проекта базы данных Ссылки на базы данных Сценарии Сценарии создания данных Сценарии изменения данных Запуск сценария Командные файлы Запросы Резюме Вопросы и ответы
288 290 290 291 293 296 298 303 306 306
ГЛАВА 9. XML и .NET
307
Обзор XML Семейство технологий XML XML и доступ к данным
308 310 312
Содержание
Классы XML на платформе .NET Применение модели Document Object Model Применение технологии ХРАТН Утилита SQLXML Инсталляция и конфигурирование утилиты SQLXML Результаты конфигурирования Применение XML, XSLT и SQLXML для создания отчета Резюме Вопросы и ответы
ГЛАВА 10. ADO.NET и XML Основные принципы чтения и записи XML-данных Чтение XML-данных Запись XML-данных Формат DiffGram Бизнес-ситуация 10.1: подготовка XML-файлов для бизнес-партнеров Создание объекта XmlReader с помощью объекта Command Объект XmlDataDocument Резюме Вопросы и ответы
ГЛАВА 11. Web-формы: приложения на основе ASP.NET для работы с базами данных Обзор технологии ASP.NET HTML-элементы управления и серверные элементы управления Дополнительные преимущества технологии ASP.NET Доступ к базе данных с помощью ASP.NET Включение учетной записи ASPNET в состав учетных записей SQL Server Применение параметра TRUSTED_CONNECTION Применение элемента управления DataGrid Повышение производительности приложений с помощью хранимых процедур Резюме Вопросы и ответы
313 313 315 318 318 325 325 327 327
329 330 330 334 340 347 359 361 364 364
367 368 369 370 371 371 376 379 382 385 385
ГЛАВА 12. Web-службы и технологии промежуточного уровня
387
Применение промежуточного уровня для презентационной логики Обработка данных на промежуточном уровне Создание повторно используемых компонентов промежуточного уровня Использование компонента в другом приложении Доступ к объектам с помощью Web-служб Публикация существующего компонента с помощью Web-службы Доступ к Web-службе программными средствами Заключительные замечания Резюме Вопросы и ответы Предметный указатель
388 391 392 395 397 399 400 403 403 404 405
Посвящается моим родителям Анн и Майку Голдштейн, наставлявшим и поддерживавшим меня на протяжении жизни. -Джеки Голдштейн, октябрь 2002 года Моей жене. - Кевин Прайс, октябрь 2002 года
Предисловие
Предисловие В этой книге рассматриваются способы создания приложений для работы с базами данных на основе Visual Basic .NET и ADO.NET. Хотя в ней описываются в основном провайдеры данных OLEDB и ODBC для .NET (глава 4, "Модель ADO.NET: провайдеры данных"), практически все примеры основаны на провайдере данных для сервера баз данных Microsoft SQL Server, которая используется большинством наших читателей. Более того, описываемые здесь подходы и концепции обычно можно очень просто применить для использования других источников данных. Все наиболее значительные отличия в способах использования этих технологий сопровождаются подробными комментариями. Предполагая, что большинство читателей уже имеют опыт работы с сервером SQL Server, мы все же постарались сделать книгу доступной и для тех, кто не имеет большого опыта работы с ним. Некоторые читатели имеют ограниченный опыт работы с приложениями для баз данных или работали с другими типами баз данных, например с Microsoft Access или Oracle. Поэтому в главе 3, "Знакомство с SQL Server 2000", предлагается краткий обзор основных приемов работы с сервером Microsoft SQL Server. Опытные специалисты SQL Server могут без ущерба для понимания остальных глав пропустить эту вводную главу. Тем не менее следует учесть, что она покрывает широкий круг тем, а потому даже опытный читатель сможет найти в ней несколько полезных советов, ради которых стоит хотя бы бегло просмотреть всю главу. Помимо основных сведений об SQL Server, здесь описываются язык XML и способы интеграции XML с ADO.NET. Этот очень важный аспект создания приложений баз данных с помощью Visual Basic .NET часто недооценивается или описывается недостаточно полно. Поскольку XML играет очень важную роль в создании современных приложений для работы с данными, эта тема излагается здесь очень подробно. В книге содержится множество листингов и примеров, которые, несомненно, помогут наилучшим образом понять предлагаемый материал. Обычно описание основных принципов иллюстрируется очень простыми примерами, а затем для описания реального контекста предлагаются типичные бизнес-ситуации.
Для кого предназначена эта книга Предполагается, что читатель уже знаком с основами Visual Basic .NET. Хотя здесь предлагаются очень подробные и последовательные инструкции по созданию кода, все же в этой книге не ставилась цель обучить читателя основам синтаксиса Visual Basic .NET. Мы считаем, что читатель уже владеет основными навыками работы с Visual Basic .NET и Visual Studio .NET, а потому решили не тратить времени на повторение общеизвестных базовых сведений. В частности, за исключением только первого примера, здесь не рассматриваются такие стандартные операции, как открытие и сохранение проектов. Наряду с этим, выполнение одной и той же операции нередко описывается несколькими разными способами, что позволит читателю расширить свои знания Visual Basic .NET без лишнего повторения одних и тех же базовых сведений. Поэтому часто приводятся разные стили кодирования и копии экранов для разных версий Windows, которые иллюстрируют гибкость Visual Basic .NET.
Предисловие
Большинство примеров этой книги демонстрируются с помощью типа проекта Windows Application на основе Windows Forms. Дело в том, что многие программисты на Visual Basic очень хорошо знают и часто используют этот тип проекта. Это позволяет нам сфокусироваться на способах доступа к базе данных, а не на особенностях использования разных типов проектов .NET. В последних главах книги описываются приложения на основе ASP.NET и Web-службы, поэтому в рассматриваемых там примерах представлены другие технологии и типы проектов.
Структура книги Книга содержит три части. Первая часть состоит из глав 1-3 с предварительными сведениями о базах данных, языке SQL и сервере баз данных SQL Server. Эти фундаментальные сведения позволят читателю познакомиться с основными концепциями и понятиями, используемыми в книге. Кроме того, эти главы содержат краткие обзоры важных тем, которые будут полезны даже очень опытным специалистам в этих областях. Вторая часть содержит основной материал книги. В главах 4-7 предлагаются подробные объяснения и многочисленные примеры основных объектов ADO.NET, a также способы использования их свойств и методов. В главе 7, "ADO.NET: дополнительные компоненты", рассматриваются более сложные компоненты и способы работы с объектами ADO.NET. В третьей части книги приводятся фундаментальные способы применения ADO.NET для создания профессиональных приложений, а также рассматриваются методы использования проектов Visual Studio Data Projects для работы со сценариями SQL (глава 8, "Работа с проектом базы данных в среде Visual Studio .NET"), язык XML (глава 9, "XML и .NET") и вопросы интеграции XML с ADO.NET (глава 10, "ADO.NET и XML"). Наконец, в последних главах описываются дополнительные типы проектов на основе ADO.NET: Web-приложения на основе ASP.NET (глава 11, "Web-формы: приложения на основе ASP.NET для работы с базами данных"), а также Web-службы и объекты промежуточного уровня (глава 12, "Web-службы и технологии промежуточного уровня").
Используемое программное обеспечение Предполагается, что читатель уже установил или способен самостоятельно установить интегрированную среду разработки приложений Visual Studio .NET. Следует учесть перечисленные различия, которые существуют между разными редакциями среды Visual Studio .NET в отношении функциональных возможностей и типа используемой базы данных. Редакция Visual Studio.NET Standard
Возможности Просмотр таблиц и данных, выполнение хранимых процедур с помощью SQL Server Desktop Engine и Access
Предисловие
Редакция Visual Studio .NET
Возможности
Professional
Просмотр таблиц и данных, выполнение хранимых процедур с помощью любой базы данных с провайдером данных OLEDB или драйвером ODBC. Проектирование (создание или изменение) таблиц или представлений с помощью SQL Server Desktop Engine
Enterprise Developer, Просмотр таблиц и данных, выполнение хранимых процедур с помоEnterprise Architect щыо любой базы данных с провайдером данных OLEDB или драйвером ODBC. Проектирование (создание или изменение) таблиц, представлений и хранимых процедур с помощью SQL Server Desktop Engine, SQL Server или Oracle В некоторых местах глав 1, 2 и 8 используются компоненты, которые предусмотрены только в редакциях Enterprise Developer или Enterprise Architect среды Visual Studio. В главе 3, "Знакомство с SQL Server 2000", предлагается подробное описание процесса инсталляции SQL Server 2000, которое будет особенно полезно для читателей, не имеющих опыта инсталляции этого программного продукта. Для тестовой базы данных pubs, которая поставляется вместе с SQL Server, рекомендуется создать резервную копию, потому что она используется во многих примерах этой книги и ее данные часто редактируются. В предлагаемых бизнес-ситуациях и многих примерах используется специально созданная для этой книги база данных Novelty. В главах 3 и 8 подробно описаны сценарии создания этой базы данных. Для использования примеров нужно сначала создать базу данных Novelty на компьютере с сервером SQL Server 2000 и наполнить ее данными. При описании этих операций предполагается, что читатель обладает всеми необходимыми правами для создания базы данных на этом сервере. Учтите, что некоторые пользователи применяют термин "база данных" к понятию "приложение для работы с базами данных", но в этой книге термин "база данных" означает "структурированный набор реляционных данных, которые хранятся в SQL Server 2000". Коды всех примеров вместе со сценариями создания и наполнения данными базы данных Novelty, которая используется в этой книге, можно найти на Web-сервере Издательского дома "Вильяме" по адресу: http://www.williamspublishing.com. Для создания этой базы данных на компьютере с SQL Server 2000 выполните ряд действий. 1. Откройте программу Query Analyzer с помощью команды StartO Programs1* Microsoft SQL Server^Query Analyzer и подключитесь к нужному серверу SQL Server. 2. Откройте файл NoveltyDB. sql, выбирая команду меню File^Open (ФайлО Открыть) и указывая место расположения этого файла. 3. После открытия этого файла его содержимое будет отображено в диалоговом окне.
Предисловие
4. Для выполнения сценария выберите команду Execute^Query (Выполнить1* Запрос) или щелкните на кнопке с изображением зеленой стрелки. 5. После выполнения сценария будет создана база данных Novelty, которую можно наполнить данными, повторяя действия, описанные в пп. 2-4, для других сценариев с суффиксом Data в имени; например, сценарий OrdersData . sql вставляет данные в таблицу с заказами. Учтите, что исходная версия 1.0 платформы .NET Framework и среда Visual Studio .NET не содержат провайдера данных для ODBC. Он входит в следующие версии и его можно скопировать отдельно с Web-узла компании Microsoft по адресу: http: //www.microsoft .com. Кроме того, там же можно скопировать провайдер данных Microsoft .NET для Oracle, если вы используете базу данных Oracle, однако учтите, что в этой книге она не описывается.
Предисловие
Об авторах Джеффри П. Мак-Манус (Jeffrey P. McManus) — разработчик и автор, специализирующийся на программных продуктах Microsoft. Как разработчик, он занимался созданием оперативных приложений на основе Internet-ориентированных и клиентсерверных технологий. Он автор четырех книг, включая предыдущее издание этой книги — бестселлер Обработка баз данных на Visual Basic® 6, а также две книги, посвященные .NET-ориентированным технологиям. Джеффри регулярно участвует в конференциях VBITS/VSLive, European DevWeek и VBConnections. Джеки Голдштейн (Jackie Goldstein) — президент компании Renaissance Computer Systems, которая специализируется на создании приложений и предоставлении консультаций в области программных продуктов и технологий Microsoft. Более 18 лет он участвует в создании и сопровождении программных продуктов в США и Израиле, а также обладает огромным опытом оказания консультационных услуг и интеграции новых технологий. Джеки является региональным директором MSDN в Израиле, основателем израильской группы пользователей Visual Basic (VB User Group). Он регулярно выступает на международных конференциях разработчиков, включая VSLive!, TechEd, VBITS, Microsoft Developer Days и SQL2TheMax. Он также работал с компанией Microsoft в качестве эксперта по основным вопросам рецензирования, усовершенствования и завершения технических материалов и презентаций для всемирных конференций Microsoft Developer Days.
О соавторе Кевин Т. Прайс (Kevin T. Price) — старший технолог, который специализируется на вопросах обеспечения безопасности и масштабирования (штат Вирджиния). В течение многих лет он сумел охватить все аспекты создания приложений с помощью набора инструментальных средств компании Microsoft. Он написал несколько глав для разных книг об XML, системе безопасности и технологиях .NET. Помимо своей основной работы, Кевин увлекается кулинарией и пейнтболом. С ним можно связаться по адресу: kpcrash@patriot. net.
Предисловие
О рецензентах Энжани Читаджаллу (Anjani Chittajallu) получила диплом мастера в области систем управления в Индийском технологическом институте (Indian Institute of Technology) в Мадрасе. Она специализируется в проектировании и разработке корпоративных систем на основе технологий Microsoft. Энжани имеет сертификат разработчика MSCD и с ней можно связаться по адресу: s r i a n j a n i @ h o t m a i l . com. Эндрю Дж. Индовина (Andrew J. Indovina) в настоящее время является старшим разработчиком программного обеспечения в Рочестере, штат Нью-Йорк (Rochester, New York). Помимо ученой степени по информатике, он обладает глубокими знаниями языков ассемблера, C/C++, Visual Basic, Java, XML, ASP и навыками программирования на них. Кроме того, он является соавтором двух книг о языках Visual Basic и C++, а также техническим редактором многочисленных книг по информатике. В последнее время Эндрю активно занимается созданием приложений на основе Microsoft .NET.
Предисловие
Благодарности Мы хотим поблагодарить тех, кто помогал нам создать эту книгу, в частности: Сондру Скотт (Sondra Scott), ответственного редактора, которая решила множество проблем в процессе создания книги; Лори Мак-Гвайр (Laurie McGuire), нашего наиболее терпеливого редактора, сделавшего очень много полезного; Кевина Т. Прайса (Kevin T. Price), который согласился принять участие в создании этой книги и пополнить главы своими материалами, несмотря на сложные обстоятельства; Энжани Читаджаллу (Anjani Chittajallu) и Эндрю Дж. Индовину (Andrew J. Indovina), технических рецензентов, которые не только проверили нашу работу, но и предложили множество полезных идей; Майкла Пизо (Michael Pizzo) из компании Microsoft, который всегда быстро отвечал на наши вопросы или рекомендовал других более опытных специалистов; наших жен, детей, родственников и друзей, которые поддерживали нас во время создания этой книги.
Основы построения баз данных
В ЭТОЙ ГЛАВЕ... » Что представляет собой база данных • Бизнес-ситуации * Манипулирование данными с помощью объектов • Типы данных * Схема базы данных »
Отношения
* Нормализация • Создание пользовательского интерфейса на основе Windows Forms • Резюме * Вопросы и ответы
Глава 1
Сердцем многих приложений, работающих в сфере бизнеса, являются базы данных. Своим широким распространением они обязаны возможности централизованного доступа к информации, который характеризуется последовательностью, эффективностью и относительной простотой создания и поддержки. В этой главе рассматриваются основы создания и поддержки баз данных, предназначенных для ведения бизнеса, т.е. здесь вы узнаете, что собой представляет база данных и как ее можно использовать для принятия решений в сфере бизнеса. Если вы уже работали с языком Visual Basic и программировали доступ к базам данных, то материал этой главы может показаться вам довольно тривиальным. Однако не стоит пропускать ее, поскольку здесь вы найдете профессиональные термины, которые могут меняться при переходе от одной системы управления базами данных (СУБД) к другой. Несмотря на относительное постоянство концепций, лежащих в основе различных СУБД, одни и те же вещи имеют обыкновение называться по-разному при переходе от одной конкретной реализации к следующей. Например, многие программисты, разрабатывающие приложения клиент/сервер, называют запросы (query), хранимые в контейнере базы данных, представлениями (view), а программисты, работающие в среде Visual Basic или Access, называют их запросами или объектами QueryDef. По своей сути это одно и то же. Если вы переходите к Visual Basic .NET от предыдущей версии Visual Basic, то вам следует познакомиться с некоторыми новыми возможностями программирования баз данных с помощью Visual Basic .NET. Дело в том, что в ней используется фундаментально другой способ доступа к данным, который отличается от способов доступа к данным в прежних версиях Visual Basic. Он основан на стандартах Internet с прицелом на создание приложений с возможностями удаленного доступа к данным. Интегрированная среда разработки Visual Studio .NET содержит огромный набор визуальных и интуитивно понятных инструментов, которые упрощают и ускоряют процесс создания баз данных и обеспечивают более высокую степень взаимодействия. Ранее для создания и поддержки баз данных необходимо было иметь глубокие знания многих инструментов. С помощью Visual Studio .NET разработчик может обратиться к многочисленным программам-мастерам, что позволяет избежать создания рутинного кода и повысить гибкость создаваемых приложений. Если же вы не понаслышке знакомы с разработкой баз данных в прежней версии Visual Basic 6.0, возможно, вам имеет смысл забежать вперед и перейти к главе 4, "Модель ADO.NET: провайдеры данных", посвященной новым способам доступа к данным в Visual Basic .NET.
Что представляет собой база данных База данных (database) — это своего рода камера хранения информации. Поскольку существуют различные типы баз данных, необходимо отметить, что в данной книге рассматриваются реляционные базы данных, как самый распространенный в настоящее время тип баз данных. Реляционные базы данных обладают следующими возможностями: •
сохраняют данные в таблицах, которые, в свою очередь, состоят из строк, называемых здесь записями, и столбцов, называемых здесь полями;
Основы построения баз данных
•
позволяют считывать подмножества данных из таблиц (или создавать для них sanpocbi);
•
позволяют связывать таблицы друг с другом (или создавать объединения) для выборки связанных записей, хранимых в различных таблицах.
Что такое платформа базы данных Основные функции базы данных обеспечиваются платформой баз данных (database platform), т.е. программной системой, "отвечающей" за способ хранения данных и их выборку. Вместе с Visual Basic .NET можно использовать множество различных платформ баз данных, но в этой книге в основном рассматривается платформа Microsoft SQL Server 2000. (Более подробно она рассматривается в главе 3, "Знакомство с SQL Server 2000".) Процессором базы данных (database engine) называется сам механизм, лежащий в основе платформы базы данных и непосредственно "отвечающий" за выполнение функций и управление данными.
Бизнес-ситуации Многие книги, посвященные компьютерному обеспечению, состоят из длинных списков программных средств с кратким описанием особенностей их работы. Если вам повезет, вы найдете описание того, как данный продукт связан с реальным миром. Цель настоящей книги — представить программное обеспечение в терминах бизнес-решений. Поэтому каждая глава содержит несколько бизнес-вариантов, в которых некая фиктивная компания, столкнувшись с реальными проблемами в сфере бизнеса, пытается автоматизировать работу офиса. В приведенных бизнес-ситуациях используются наработки компании Jones Novelties Incorporated, которая занимается так называемым малым бизнесом— распространением сувениров, мелких дешевых товаров и организацией вечеринок.
Бизнес-ситуация 1.1: основные сведения о компании Jones Novelties Incorporated Исполнительный директор компании Брэд Джонс сознает, что для процветания компании нужно автоматизировать большую часть проводимых операций. Джонс понимает, что в первую очередь необходимо реализовать такие подсистемы, которые отвечают за контакты с покупателями, складское хозяйство и выписку счетов, причем реализация проекта автоматизации должна максимально отражать специфику этого бизнеса и в то же время отличаться достаточной гибкостью, позволяя вносить потенциальные изменения, продиктованные временем. Джонс полностью сознает, что успех работы компании во многом зависит от характера организации доступа к информации, и принимает решение использовать для управления информацией компании систему реляционных баз данных. Поэтому последующий материал главы посвящен описанию структуры и особенностей функционирования этой базы данных.
Глава 1
Таблицы и поля Базы данных состоят из таблиц, которые представляют широкий диапазон категорий данных. Если когда-либо вам приходилось создавать базу данных, например для обработки отчетных материалов в бизнесе, то вы могли создать одну таблицу для хранения информации о клиентах, другую — о счетах, третью — о сотрудниках. Таблицы имеют заранее определенную структуру, и данные, хранящиеся в них, соответствуют этой структуре. Таблицы содержат записи— отдельные частицы данных внутри широкой категории, которую они представляют. Например, таблица с клиентами содержит информацию обо всех потребителях товаров и услуг данной компании. Записи могут содержать данные практически любого типа. Они могут редактироваться, извлекаться и удаляться с помощью хранимых процедур и/или запросов на языке структурированных запросов (Structured Query Language — SQL). Записи, в свою очередь, содержат поля. Поле — это некоторый раздел данных в записи. Например, запись, которая представляет некий элемент в адресной книге, может состоять из полей имени и фамилии, адреса, названия города, почтового индекса и номера телефона. Для доступа к базам данных, таблицам, записям и полям можно использовать код Visual Basic .NET. Одна из новинок программирования баз данных в Visual Basic .NET заключается в строгой проверке типов данных. Например, в Visual Basic .NET предусмотрены новые методы getStringO и g e t l n t ( ) , которые позволяют сократить объем вводимого программистом кода и автоматически форматируют извлекаемые данные согласно их типу.
Проектирование базы данных Для создания базы данных в первую очередь нужно определить, какого рода информацию ей предстоит отслеживать. Затем можно приступать к проектированию, создавая таблицы, состоящие из полей, которые определяют типы хранимых данных. После создания структуры базы данных можно сохранять данные в виде записей. Однако невозможно добавлять данные в базу данных, которая не имеет таблиц или определений полей, поскольку в этом случае негде хранить данные. Отсюда следует, что проектирование базы данных имеет решающее значение для эффективности ее работы, в частности потому, что структура базы данных после ее реализации порой тяжело поддается изменениям. В этой книге таблицы представлены в стандартном схематичном формате. В верхней части схемы приводится имя таблицы, а под ним — список названий полей. ММуТаЫе
ID
FirstName LastName
Основы построения баз данных
Многоточие, использованное вместо последнего имени поля, означает, что эта таблица имеет одно или несколько полей, которые для краткости изложения опущены. Если вы новичок в мире программирования баз данных, но раньше использовали другие компьютерные приложения, вас, возможно, удивит, что приложение базы данных заставляет решать массу проблем еще до того, как вы приступите ко вводу данных. Например, приложение обработки текстов позволяет просто набирать и редактировать текст, а подробности, связанные с сохранением файла, вас не касаются — они решаются самим приложением. Однако с базами данных все обстоит по-другому, потому что заблаговременное проектирование структуры баз данных значительно повышает эффективность работы приложения. Если приложению будет известен точный объем и типы данных, подлежащих хранению, то процесс их сохранения и выборки может быть организован оптимальным образом. Создав свою первую многопользовательскую базу данных на 100 тыс. записей, вы узнаете, что первостепенным фактором в работе базы данных является скорость выборки. Поэтому особого внимания заслуживают любые усилия, направленные на ускорение процесса добавления информации в базу данных и выборки из нее. Эффективность работы баз данных зависит от продуманности структуры таблиц, т.е. одна и та же таблица должна включать поля, относящиеся к одной и той же категории данных. Это значит, что все записи с данными о клиентах должны храниться в таблице Customer, записи о заказах, оформляемых этими клиентами,— в таблице Orders и т.д. Хотя эти наборы данных входят в различные таблицы, это вовсе не означает, что вы не можете использовать их вместе. Совсем наоборот. Если необходимые данные расположены в двух или нескольких таблицах реляционной базы данных, вы можете получить доступ к этим данным, используя отношения между таблицами. Отношения будут рассмотрены ниже, а пока остановимся на структуре таблиц.
Бизнес-ситуация 1.2: проектирование таблиц и отношений Брэд Джонс понял, что компании Jones Novelties Incorporated необходим способ сохранения информации о клиентах. Он совершенно уверен в том, что большинство его деловых контактов не будут однократными, и поэтому хочет иметь возможность связываться с постоянными клиентами, чтобы отсылать им каталоги два раза в год. Размышляя таким образом за коктейлем, Брэд начертил на салфетке первую схему базы данных. "Итак, — подумал он, — чтобы поддерживать контакты с клиентами, мне нужно хранить следующие данные: • •
имя клиента, его адрес, город, штат, почтовый индекс и телефонный номер; территориальный регион страны (северо-запад, юго-запад, средний запад, северо-восток, юг или юго-восток);
• дату последней покупки клиента". Брэд предположил, что всю эту информацию можно поместить в одну таблицу и тогда его база данных будет отличаться изяществом и простотой. Однако в команде разработчиков нашлись отважные люди, которые осмелились сказать своему шефу,
Глава 1
что, возможно, он и прав, но построенная таким образом база данных будет неэффективной, неорганизованной и чрезвычайно негибкой. Информация, которую Брэд хочет включить в таблицу, не преобразуется напрямую в ее поля. Например, поскольку регион является функцией от штата, в котором проживает данный клиент, то вряд ли имеет смысл помещать поля State и Region в одну таблицу. Если все-таки пойти на это, то оператору, занимающемуся вводом данных, придется дважды вводить аналогичную информацию о клиенте. Логичнее хранить поле State в таблице Customer, а остальные сведения, относящиеся к регионам, — в таблице Region. Если по таблице Region всегда можно определить, в каком регионе находится тот или иной штат, то оператору не придется вводить регион для каждого клиента. Вместо этого достаточно ввести только название штата, а затем после обработки данных из таблиц Customer и Region автоматически будет определен регион проживания данного клиента. Точно так же критически следует посмотреть на поле Name. Если вместо поля Name использовать два поля: FirstName и LastName, то это облегчит сортировку по фамилии клиентов, если таковая потребуется. Подобный аспект проектирования может показаться тривиальным, но остается лишь удивляться тому, сколько проектов баз данных не учитывают таких простых вещей, как эти. Важно понять, что все это гораздо легче предусмотреть на этапе проектирования базы данных, чем пытаться исправить дефекты, вызванные недальновидностью разработчиков, когда база данных уже заполнена информацией. Поэтому Брэд и его сотрудники решили, что информация о клиентах компании Jones Novelties Incorporated будет храниться в таблице tblCustomer, которая содержит перечисленные ниже поля. tblCustomer
ID
FirstName LastName Company Address City State PostalCode Phone Fax
Email Данные, относящиеся к региону страны, в котором проживает клиент, следует хранить в таблице tblRegion.
Основы построения баз данных
tblRegion
ID
State RegionName Между двумя этими таблицами существует отношение по полю State. Обратите внимание на то, что это поле присутствует в обеих таблицах. Отношение между таблицами Region и Customer является отношением один-ко-многим, поскольку для каждой записи в таблице tblRegion может существовать или одна, или ни одной, или много записей в таблице tblCustomer, совпадающих по полю State. (Далее в главе подробно описывается, как воспользоваться преимуществами такого отношения при выборке записей.) Обратите внимание на то, какие имена были присвоены таблицам и полям этой базы данных. Во-первых, имя каждой таблицы начинается с префикса tbl Этот префикс позволяет с первого взгляда определить, что вы имеете дело именно с таблицей, а не с другим типом объектов базы данных, в котором могут храниться записи. Заметьте, что каждое имя поля состоит из полных слов (а не сокращений), но не включает пробелов или таких специальных символов, как символы подчеркивания. Несмотря на то что механизм управления базами данных Microsoft SQL Server позволяет использовать в именах объектов баз данных пробелы, символы подчеркивания и другие символы, не входящие в число алфавитно-цифровых, все-таки стоит избегать их использования, поскольку это затрудняет запоминание точного написания имени поля. (В этом случае вам не придется, например, гадать, как называется поле, содержащее имя: FirstName или FIRST_NAME.) Эта директива может показаться сейчас незначительной, но, когда вы начнете писать код для базы данных, содержащей 50 таблиц и 300 полей, вы по достоинству оцените существующие соглашения о присвоении имен, особенно на первом этапе разработки. Рассмотрим последний пункт из предварительного списка Брэда, предусматривающий регистрацию ответа на вопрос: "Когда данный клиент в последний раз делал у нас покупку?". Разработчик базы данных решил, что эта информация может храниться в таблице, которая предназначена для хранения данных, относящихся к заказам клиентов. Ниже приведена структура этой таблицы. tblOrder
ID
CustomerlD OrderDate Amount В этой таблице поле ID уникальным образом идентифицирует каждый заказ. Поле CustomerlD, с другой стороны, связывает заказ с клиентом. Чтобы установить эту связь, идентификатор клиента копируется в поле CustomerlD таблицы Order. Таким образом, совсем нетрудно отыскать все заказы для конкретного клиента (как будет продемонстрировано, ниже).
Глава 1
Манипулирование данными с помощью объектов После создания таблиц можно приступить к манипуляциям с данными: вводить данные в таблицы, извлекать их из таблиц, проверять и изменять структуру таблиц. Для манипулирования структурой таблиц используются команды определения данных (более подробно они описываются в главе 2, "Запросы и команды на языке SQL"), а для манипулирования данными — объекты DataSet или DataReader платформы .NET. Объект DataSet обычно представляет подмножество записей, которые извлекаются из базы данных. Оно концептуально аналогично таблице (а в некоторых случаях— группе связанных полей), но также содержит несколько важных собственных свойств. Объекты DataSet можно легко представить в виде XML-данных и использовать для передачи удаленных данных (как, например, при передаче результатов выполнения запроса от сервера к клиенту или при обмене данными между двумя серверами). В Visual Basic .NET объекты DataSet не ограничены только сохранением извлеченных данных. Например, объект DataSet может использоваться для управления статическими данными в XML-документе или файле конфигурации, либо для управления динамическими данными, созданными на основе пользовательских данных в более сложных ситуациях. Как и при работе с технологией ADO, в Visual Basic .NET и ADO.NET можно использовать подключенные и неподключенные объекты DataSet. Неподключенный объект DataSet с данными передается приложению, соединение с базой данных закрывается, а базе данных ничего не известно о манипуляциях с этими данными до тех пор, пока приложение вновь не обратится к базе данных. Допустим, что пользователь открывает форму и щелкает на кнопке для обновления данных. В таком случае приложение должно снова соединиться с базой данных и выполнить код изменения данных. В то же время с помощью подключенного объекта DataSet используемые данные "блокируются" и все изменения данных мгновенно воспроизводятся в базе данных. Эта технология более подробно рассматривается в главе 5, "ADO.NET: объект DataSet". Объект DataReader работает аналогично объекту DataSet, но обладает другими возможностями и характеристиками производительности. Одно из отличий отражено в его названии: объект DataReader считывает данные, т.е. он предоставляет доступ к данным только для чтения. Для объекта DataReader также не предусмотрен простой способ представления данных в формате XML. Для простоты (что также рекомендуется делать на практике) в данной книге объ-' ект DataReader используется для выполнения базовых операций доступа к данным, а объект DataSet— только в случае крайней необходимости, например для создания Web-служб (более подробно они рассматриваются в главе 12, "Web-службы и технологии промежуточного уровня"). Объект DataSet устроен так же, как и объект ADODB.Recordset в прежних версиях, языка Visual Basic. Аналогично другим типам объектов языка Visual Basic, объект DataSet имеет свойства и методы. Более подробно он рассматривается в других главах книги, а здесь достаточно отметить, что на платформе .NET объекты используются для организации в приложении ясного, согласованного и относительно простого способа работы с базами данных.
Основы построения баз данных
Типы данных Один из этапов проектирования базы данных заключается в объявлении типа каждого поля, что позволяет процессору базы данных эффективно сохранять и извлекать данные. В SQL Server предусмотрено использование 21 типа данных, которые перечислены в табл. 1.1.
Таблица 1.1. Типы данных в SQL Server Тип данных
Описание
bigint
Восьмибайтовое целое число в диапазоне от -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807
binary
Двоичные данные фиксированного размера до 8 Кбайт
char
Символьное поле фиксированного размера до 8000 символов
datetime
Время и дата между 1 января 1753 года и 31 декабря 9999 года
decimal
Десятичное число с фиксированной точностью и размером от 5 до 17 байт. Во время создания поля можно указать число десятичных знаков
float
Десятичное число размером от 4 до 8 байт и не более 53 десятичных знаков после запятой
image
Двоичные данные переменного размера до 2 147 483 647 байт
int
Четырехбайтовое целое число в диапазоне от -2 147 483 648 до 2 147 483 647
money
Числовое поле со специальными свойствами для сохранения денежных значений
nchar
Символьное поле фиксированного размера до 4000 символов Unicode
ntext
Символьное поле произвольного размера до 1 073 741 823 символов Unicode
nvarchar
Символьное поле произвольного размера до 4000 символов Unicode
real
Десятичное число размером 4 байта и не более 24 десятичных знаков после запятой
smalldatetime
Время и дата между 1 января 1900 года и 6 июня 2079
smallint
Двухбайтовое целое число в диапазоне от -32 768 до 32 767
text
Символьное поле произвольного размера до 2 147 483 647 символов (в базе данных Microsoft Access есть аналогичное поле типа Memo)
tinyint
Однобайтовое целое число в диапазоне от 0 до 255
uniqueidentifier Целое число, которое также называется глобально уникальным идентификатором и используется для уникальной идентификации записи (часто применяется для репликации данных) varbinary
Двоичные данные переменного размера до 8000 байт
varchar
Символьные данные переменного размера до 8000 символов
Глава 1
Хотя типы данных Visual Basic .NET более близки к типам данных полей SQL Server, чем типы данных Visual Basic 6, между ними все равно нет однозначного соответствия. Например, тип данных int в SQL Server соответствует типу integer в Visual Basic .NET, потому что оба они являются 32-битовыми целыми числами. Однако в SQL Server нельзя создать поле с определенным пользователем типом или типом Ob j ect языка Visual Basic .NET.
Схема базы данных Для создания структуры базы данных рекомендуется не только подготовить список таблиц и полей, но и представить таблицы и поля в графическом виде. После этого вы не только сможете сказать, какие таблицы и поля доступны для вас, но и как они связаны друг с другом. Именно для этого и предусмотрена схема базы данных. Схему можно представить как карту дорог для вашей базы данных. На схеме все таблицы, поля и отношения в базе данных изображаются графически. Схему базы данных важно рассматривать как часть процесса проектирования программного продукта, поскольку с ее помощью можно быстро понять, что происходит в базе данных. Схемы не теряют своей актуальности и после завершения процесса проектирования базы данных. Без такой схемы вам будет трудно выполнять многотабличные запросы. Толково составленная графическая схема поможет ответить на вопросы типа: "Какие таблицы мне нужно объединить, чтобы составить список всех заказов с объемом, превышающим $50,00, поступивших от клиентов из штата Миннесота в течение последних 24 часов?" (За дополнительной информацией по созданию запросов, включающих более одной таблицы, обращайтесь к главе 2, "Запросы и команды на языке SQL".) Официальных способов создания схем баз данных не существует, но есть много средств, которыми можно воспользоваться при их создании. Например, графический редактор Visio отличается гибкостью, быстротой и простотой применения. Более того, он хорошо интегрируется с другими приложениями Windows, в частности с Microsoft Office. Этот редактор распространяется отдельно, а также входит в состав Visual Studio .NET Enterprise Architect. Все сказанное в пользу Visio не означает, что при создании графической схемы базы данных вы должны использовать только программу Visio. Можно применять любые другие инструменты рисования, с которыми вы знакомы. Приемлемый вариант — программа Microsoft Windows Paint, можно также воспользоваться средствами рисования, предусмотренными в программе Microsoft Word.
Использование инструментов Visual Studio для создания базы данных Существует несколько способов создания баз данных в SQL Server. С помощью набора инструментов SQL Enterprise Manager базы данных можно создавать графически или программно (с помощью команд на языке SQL). Помимо него, существует множество других внешних инструментов для создания баз данных, например Visio, который описывается далее в главе.
Основы построения баз данных
Visual Studio .NET также содержит очень удобный инструмент для работы с базами данных SQL Server. Он входит в состав нового компонента Server Explorer, который предназначен для централизованного управления всеми видами серверного программного обеспечения. Для создания базы данных SQL Server с помощью компонента Server Explorer выполните перечисленные ниже действия. 1. Запустите интегрированную среду разработки Visual Studio .NET, выбрав команду меню Startoprograms^Microsoft Visual Studio .NEToMicrosoft Visual Studio .NET. 2. В левой части окна Visual Studio .NET откройте окно Server Explorer, выбрав команду меню ViewOServer Explorer (учтите, что эта вкладка может иметь горизонтальную или вертикальную ориентацию). 3. В этом окне раскройте узел Servers, найдите ваш компьютер, а затем раскройте узел SQL Servers и найдите в нем экземпляр SQL Server, который установлен на вашем компьютере, как показано на рис. 1.1.
В-
Data Connectiwis Servers В- В rocko El «*
В*
fc*ug
- Database
йиегу
Icds
Sfflndow
ИИ-Ш
ttelp
' ifl • 53 - а? Й 0 - •; • t-з I» > ••• ! - - > n*buo - ! ф ; novelty - SQl Server 200D Database [design] - DatnbaseOiagram'/ : Oalabate Diagram ffe
Е*
View
Ero|ect
Diabase
Diagram
loote
ffiindow
ЦФ
,
5iP-ii-s*H9; * чаши-' • ••-• ~jn-q ,
"
>: ! Ш *Ь *? : Q, =/• li :|T]alb | TatteVjew- j % \ ~b [Pj ; В :£ cjg i ш _
„ *_,ili Databa«!Dfagr™QCO.no»eltY)*
t'jp Data Connections >, El- % Servers id- Ш rocko Г+i »i* Crystal Services Щ И Event Logs ;+. •*( Message Queues Ш- £3 Performance Counters ;*; ^j Services В It SQL Servers H % ROCKO I Й- Manager) либо у вас нет программы Visio, то в таком случае можно пропустить дан- i ный раздел без ущерба для понимания остального материала. _ : ..:, Реинжиниринг (reverse engineering) базы данных заключается в проверке схемы существующей базы данных и создании диаграммы отношений между объектами базы данных (Entity Relationship Diagram — ERD). ERD-диаграмма — это способ символьного представления базы данных, основанный на широких категориях данных, или сущностях (entities), которые обычно хранятся в базе данных в виде таблиц. Для реинжиниринга схемы базы данных с помощью программы Visio выполните перечисленные ниже действия. 1. Запустите программу Microsoft Visio 2002 for Enterprise Architects, выбрав команду Start^ProgramsoMicrosoft Visio. В панели Choose Drawing Type (Выбрать тип рисования) выберите категорию Database (База данных). 2. Затем в панели Template (Шаблон) выберите параметр Database Model Diagram (Схема базы данных), и на экране появится основное окно программы Visio (рис. 1.8). 3. Выберите команду меню Database^ Reverse Engineer (База данныхОРеинжиниринг) для запуска программы-мастера Reverse Engineer Wizard. 4. Из списка Installed Visio drivers (Инсталлированные драйверы Visio) выберите драйвер Microsoft SQL Server. 5.
Затем нужно определить источник данных, который позволит получить доступ к базе данных Novelty. Для этого щелкните на кнопке New.
6. На экране появится диалоговое окно Create New Data Source (Создать новый источник данных) с предложением указать тип создаваемого источника данных. Выберите источник данных System Data Source и щелкните на кнопке Next.
Глава 1
, ,
EJ He
&ft
View
Insert
Fmnat
>
.-ел
loots' 'shape
: |: Normal
- Ariel
Shapes .;11 Entty RefettonshJp
Errty
ftrt*ion*...
- t^r
-
П X
Мн "
•» .-«ч
|0 object Relattewl Tablet .ndVic.,1
о х
~JlJ '
DatabasePropertcs
Xoutp Ю OtderD ItemID Quantity Cost
ыыыапо - г
Defntion ФссЬтгв Primary ID Indexes Triggers , Check Extended Notes
4fl
Add
|
feemoyfl E*.» ; |
Move Bo*" j
шЛ
1
Jho «i Г portable data type
(f Ehysfcal data type (Mto-osoft SQL Server)
1 I x \ Oatabase PropcrtiM X Output /
Wkth-1.036 in.
Angle «0°
facjel/i
РИС. 1.12. Схема базы данных с отношениями между четырьмя таблицами Полями, создающими отношение, являются первичный ключ (представленный выше в этой главе) и внешний (foreign) ключ. Внешний ключ — это ключ в связанной таблице, который хранит копию первичного ключа из основной таблицы. Предположим, у вас есть таблицы с характеристиками отделов и сотрудников компании. Отношение между отделом и группой сотрудников можно определить типом один-ко-многим. Каждому отделу присваивается собственный идентификационный номер (ID), и каждый сотрудник имеет свой ID. Но, чтобы указать, в каком отделе работает каждый сотрудник, необходимо сделать копию номера ID отдела в каждой записи, содержащей данные о сотруднике. Итак, чтобы идентифицировать каждого со-
Основы построения баз данных
трудника как члена некоторого отдела, в таблице Employees (Сотрудники) должно быть предусмотрено поле (именуемое, допустим, Department ID) для хранения ID отдела, в котором работает данный сотрудник. Поле Department ID в таблице Employees служит внешним ключом таблицы Employees, поскольку хранит копию первичного ключа таблицы Departments (Отделы). Благодаря отношению процессор баз данных "знает", какие две таблицы участвуют в этом отношении и какой внешний ключ связан с первичным ключом. Для прежнего процессора Jet базы данных Access явное объявление отношений не обязательно, но это в ваших же интересах, поскольку при таком объявлении упрощается задача выборки данных из записей двух или нескольких связанных таблиц (подробнее об этом в главе 2, "Запросы и команды на языке SQL"). Отсутствие такого объявления — один из основных недостатков технологии Jet, который можно устранить с помощью переноса унаследованных приложений на основе технологии Jet на платформу ADO.NET. Помимо соответствия связанных записей в отдельных таблицах, отношение определяется для того, чтобы воспользоваться преимуществами ссылочной целостности, под которой понимают свойство процессора базы данных, обеспечивающее непротиворечивость информации, хранимой в многотабличной базе данных. Когда ссылочная целостность имеет место в базе данных, то процессор баз данных препятствует удалению записи в случае, если в базе данных существуют другие записи, связанные с ней. После того как вы определите отношение в базе данных, это определение сохраняется до тех пор, пока вы не удалите его. Отношения можно создавать графически, используя инструменты Visual Studio .NET, SQL Enterprise Manager, Visio, или с помощью сценариев на языке DDL.
Использование ссылочной целостности для поддержания непротиворечивости данных Когда таблицы связаны между собой посредством отношений, данные в каждой из связанных таблиц должны оставаться согласованными друг с другом. Ссылочная целостность справляется с этой задачей, отслеживая отношения между таблицами и запрещая выполнение определенных типов операций над записями. Допустим, у вас есть таблицы tblCustomer и tblOrder. Эти две таблицы связаны через общее поле ID. Предполагается, что сначала вы регистрируете клиентов в таблице tblCustomer, а затем создаете записи с информацией о заказах в таблице tblOrder. Но что произойдет, если запустить процесс, удаляющий запись с данными о клиенте, который оформил заказы, зарегистрированные в таблице tblOrder? А если создать заказ, для которого не существует действительного значения поля CustomerlD? Любой заказ без значения поля CustomerlD не будет отгружен, поскольку адрес отгрузки представляет собой функцию от записи в таблице tblCustomer. Когда данные в связанных таблицах страдают от такого рода проблемы, их называют несогласованными или противоречивыми. Поскольку очень важно, чтобы база данных не стала противоречивой, во многих процессорах баз данных (включая SQL Server) предусмотрен способ определения
Глава 1
формальных отношений между таблицами. При формальном определении отношения между двумя таблицами процессор баз данных отслеживает это отношение и препятствует выполнению любой операции, которая "покушается" на ссылочную целостность. Ссылочная целостность обеспечивается путем генерирования ошибок при выполнении действия, которое могло бы оставить данные в противоречивом состоянии. Например, в базе данных с активизированной ссылочной целостностью при попытке создать заказ, содержащий идентификационный номер (ID) клиента, которого на самом деле не существует, вы получите сообщение об ошибке и "подозрительный" заказ не будет создан.
Проверка ограничений ссылочной целостности с помощью Server Explorer Для проверки отношения между таблицами tblCustomer и tblOrder попробуем использовать окно Server Explorer среды Visual Studio .NET. Для этого выполните перечисленные ниже действия. 1. Откройте схему базы данных Novelty с двумя таблицами— tblCustomer и tblOrder. Обратите внимание на то, что эта схема содержит и другие таблицы, но в данном случае нас интересует отношение между этими таблицами. 2. Щелкните правой кнопкой мыши на линии отношения между двумя этими таблицами и из контекстного меню выберите команду Property Pages. 3. После появления на экране страницы свойств данного отношения выберите вкладку Relationships, в которой указаны поле ID таблицы tblCustomer, поле Customer ID таблицы tblOrder и ограничения ссылочной целостности в нижней части.
По умолчанию при создании отношения задаются ограничения ссылочной целостно- : сти (например, нельзя создать заказ для несуществующего клиента), но не заданы • условия каскадного удаления. Более подробно эти условия рассматриваются далее. 4. Установите флажок Enforce Relationship for INSERTS and UPDATES (Применять каскадное обновление и удаление), а затем щелкните на кнопке Close. 5. Для сохранения внесенных изменений выберите команду File1*Save Relationships. Для проверки заданного ограничения выполните перечисленные ниже действия. 1. В окне Server Explorer щелкните правой кнопкой мыши на таблице tblOrder и выберите из контекстного меню команду Retrieve Data from Table. 2. Введите заказ для клиента с идентификатором 9999, которого на самом деле нет в таблице с данными о клиентах. 3. Перейдите в другую строку для автоматического сохранения введенного заказа. В результате на экране появится диалоговое окно с предупреждением: INSERT
Основы построения баз данных
statement conflicted with COLUMN FOREIGN KEY constraint ' FK_ tblOrder_tblCustomer'. Conflict occurred in database 'Novelty', table 'tblCustomer', column ' I D ' . The statement has been terminated. (Команда INSERT конфликтует с ОГРАНИЧЕНИЕМ ПО ВНЕШНЕМУ КЛЮЧУ 'FK_tblOrder_tblCustomer'. Конфликт произошел в базе данных 'Novelty', таблице 'tblCustomer', поле 'ID'. Выполнение команды прекращено.) 4. Щелкните на кнопке ОК в окне с предупреждением и отмените команду вставки новой записи с помощью клавиши . В данном случае наша цель заключалась не во вводе нового заказа, а в демонстрации сообщения об ошибке. Однако если вам действительно нужно создать заказ, то в таком случае следует создать запись для клиента, получить его идентификатор ID и использовать его в поле CustomerlD при создании заказа. В рабочем приложении эта проблема обычно решается автоматически с помощью специально созданного пользовательского интерфейса. Далее в книге рассматривается несколько стратегий согласованного управления связанными данными.
Каскадные обновления и каскадные удаления Каскадные обновления и каскадные удаления — весьма полезные свойства процессора баз данных SQL Server. И вот почему. • Каскадные обновления. При изменении значения первичного ключа таблицы связанные данные во внешних ключах, относящихся к этой таблице, также изменяются, отражая изменения в первичном ключе. Следовательно, если вы измените идентификатор ID клиента Хокки Марта (Hockey Mart) в таблице tblCustomer с 48 на 72, то значение поля CustomerlD всех заказов, сгенерированных этим Хокки Мартом в таблице tblOrder, автоматически изменится с 48 на 72. В рабочем приложении редко приходится изменять значения ключа (основная концепция заключается в том, что ключ должен быть уникальным и неизменным), но если это все-таки приходится делать, то все каскадные обновления этого ключа во внешних ключах будут выполнены автоматически. • Каскадные удаления. При удалении записи в таблице все записи, связанные с этой записью в соответствующих таблицах, автоматически удаляются. Следовательно, если вы удалите запись для Хокки Марта в таблице tblCustomer, все записи в таблице tblOrder для клиента Хокки Марта автоматически удаляются.
Устанавливая отношения, выполняющие каскадные обновления и удаления в базе | данных, следует проявлять определенную осторожность. При недостаточной бди| тельности можно допустить удаление (или обновление) большего объема данных, ! чем ожидалось. Некоторые разработчики базы данных вообще отказываются от кас; кадного обновления и удаления, предпочитая явное управление ссылочной целостi ностью данных среди связанных таблиц. Однако, более внимательно изучив особенности каскадного обновления и удаления, можно убедиться в том, что они довольно : легко программируются.
Глава 1
Каскадные обновления и удаления работают только в том случае, если вы установили отношение между двумя таблицами. Если вы всегда создаете таблицы с первичным ключом типа AutoNumber (Счетчик), (или первичными ключами типа Autolncrement в терминах SQL Server), то каскадные удаления для вас окажутся более полезными, чем каскадные обновления, поскольку вы не в силах изменить значение поля типа AutoNumber или поля Autolncrement (т.е. нет обновлений — нечего и тиражировать). Для проверки возможностей каскадного удаления с помощью окна Server Explorer выполните перечисленные ниже действия. 1.
Убедитесь в том, что между таблицами tblCustomer и tblOrder задано отношение с каскадным удалением. (Для проверки или указания этого ограничения воспользуйтесь схемой базы данных.)
2. Создайте запись о новом клиенте, щелкнув правой кнопкой мыши на таблице tblCustomer узла Tables в окне Server Explorer, выбрав в контекстном меню команду Retrieve Data from Table и введя необходимые данные. Запомните идентификатор ID, присвоенный процессором базы данных новому клиенту, потому что он потребуется для создания заказов данного клиента. Пусть эта таблица остается открытой, потому что она нам еще понадобится чуть позже. 3.
Откройте таблицу tblOrder и создайте 2-3 заказа для нового клиента. Для этого укажите в поле CustomerlD идентификатор ID, присвоенный процессором базы данных новому клиенту. Пусть эта таблица также остается открытой.
4. Вернитесь к таблице tblCustomer и попытайтесь удалить запись с данными этого клиента, щелкнув правой кнопкой мыши на левом конце записи и выбрав из контекстного меню команду Delete. 5. После этого на экране появится диалоговое окно с предупреждением и просьбой подтвердить удаление данных. Щелкните на кнопке Yes. 6. Вернитесь к таблице tblOrder, и вы обнаружите, что заказы этого клиента не удалены. Что произошло? На самом деле они удалены, но дают устаревшее представление данных. Для его обновления нужно выбрать команду меню Query=>Run (Запрос1^Запуск). После этого вид таблицы будет обновлен и связанные заказы данного клиента будут удалены благодаря параметрам каскадного удаления.
Нормализация Нормализация— это тесно связанное с отношениями понятие, которое означает устранение противоречий и повышение эффективности базы данных. Базы данных считаются противоречивыми, если данные одной таблицы не соответствуют данным другой. Например, если ряд ваших сотрудников считают, что Арканзас находится на западе, а остальные — что на юге, при этом те и другие выполняют ввод данных, опираясь только на свои знания, то отчеты о состоянии дел на западе будут недостоверными. Неэффективная база, данных, как правило, не позволяет выделять именно те данные, которые вам требуются. Если база данных хранит всю информацию в одной таблице, вы можете просто потерять самообладание, пока найдете в ней нужный теле-
Основы построения баз данных
фонный номер. С другой стороны, полностью нормализованная база данных хранит каждую частицу информации в отдельной таблице и уникальным образом идентифицирует ее собственным первичным ключом. Нормализованные базы данных позволяют ссылаться на любую частицу информации в любой таблице, используя первичный ключ. При проектировании и инициализации базы данных нужно решить, как ее нормализовать. Обычно все, что связано с приложением базы данных (от структуры таблиц до структуры запросов, от пользовательского интерфейса до поведения отчетов), вытекает из характера нормализации вашей базы данных.
Как разработчику баз данных, вам еще придется столкнуться с базами данных, кото! рые не нормализованы по той или иной причине. Недостаток нормализации может [быть намеренным (например, для достижения более высокой производительности) или оказаться результатом неопытности либо небрежности разработчика базы данI ных. В любом случае, если вы собираетесь нормализовать существующую базу дан1 ных, вам нужно сделать это как можно раньше (поскольку все остальное в разработке базы данных зависит от структуры ее таблиц). Кроме того, для приведения в порядок базы данных с недостаточно продуманной структурой можно использовать команды {:, языка определения данных. Они позволяют переносить Данные из одной таблицы в I другую, а также добавлять, обновлять и удалять из таблиц записи, отвечающие за] данному критерию. В качестве примера выбора варианта нормализации можно создать проект базы данных и рассмотреть требование, выдвинутое Брэдом Джонсом в бизнесситуации 1.2. Ему требуется способ хранения названия штата, в котором проживает клиент, а также информации о регионе страны, к которому относится этот штат. Начинающий разработчик может создать одно поле для хранения названия штата, а второе — для названия региона страны. tblCustomer
ID
FirstName LastName Address Company City State PostalCode Phone Fax
Email Region
Глава 1
Эта структура первоначально может показаться рациональной, однако посмотрим, что произойдет, если кто-нибудь постарается ввести данные в приложение, основанное на этой таблице. Если бы вы вводили обычную информацию о клиенте— имя, адрес и т.д., то после ввода названия штата вам бы пришлось задуматься, чтобы определить регион проживания данного клиента. Где же находится этот Арканзас — на западе или на юге? Где находится клиент с Виргинских островов? Если существует большая вероятность ошибки, то такого рода решения не стоит оставлять в руках операторов, занимающихся вводом данных, даже несмотря на их высокую квалификацию. Если же полагаться только на человеческую память, то рано или поздно ваши данные станут противоречивыми. А чтобы защитить данные от противоречивости, и следует обращаться к нормализации. Вместо того чтобы при регистрации каждого нового клиента возлагать процесс принятия решения на операторов ввода, лучше хранить информацию, связанную с регионами, в отдельной таблице. Эту таблицу можно было бы назвать tblRegion; структура ее совсем проста. tblRegion ID
State Region Данные в этой таблице выглядели бы следующим образом: State
Region
АК
Север
AL
Юг
AR
Юг
AZ
Запад
В этой усовершенствованной версии структуры базы данных для выборки информации о регионе вам придется выполнить двухтабличный запрос с объединением двух таблиц— tblCustomer и tblRegion, причем из одной таблицы вы получите информацию о штате, а из другой — о регионе (на основании информации о штате). В объединениях сопоставляются записи, имеющие общие поля, в отдельных таблицах. (Более подробно объединения описываются в главе 2, "Запросы и команды на языке SQL".) Хранение информации о регионах в отдельной таблице имеет ряд преимуществ. •
Если вы решили выделить новый регион на основе существующего, то для отражения рождения нового региона проще изменить всего несколько записей в таблице tblRegion, чем тысячи записей в таблице tblCustomer.
•
Если вы расширите свой бизнес за пределы 50 штатов, то для отражения изменений в бизнесе достаточно опять-таки добавить новый регион. Для этого вам понадобится внести в таблицу tblRegion всего по одной записи для каждой новой области, и эта новая запись немедленно станет доступной для всей системы.
Основы построения баз данных
•
Если обнаружится необходимость использования принципов регионального деления в других задачах, решаемых на основе этой базы данных (например, для обозначения того, что офис по продажам, расположенный в определенном штате, обслуживает определенный регион), то вы могли бы с успехом использовать таблицу tblRegion без модификаций.
Отсюда вытекает, что для отдельных категорий информации следует всегда ориентироваться на создание отдельных таблиц. Во время разработки структуры базы данных (еще до реального построения самой базы данных) необходимо хорошо продумать, какие таблицы вам нужны и как они будут связаны друг с другом. Создание схемы базы данных (см. раздел о создании схемы базы данных выше в этой главе) является частью этого важного процесса.
Отношения типа один-к-одному Предположим, в вашей базе данных есть таблицы, в которых хранится информация о сотрудниках и видах работ. Если каждому служащему назначается один вид работы, то отношение между сотрудниками и видами работ можно определить типом один-к-одному, поскольку для каждого сотрудника в базе данных существует только один вид работы. Это простейший тип отношений как для понимания, так и для реализации, поскольку в таких отношениях таблица обычно занимает место поля в другой таблице, причем поля, участвующие в отношении, легко идентифицировать. Однако это не самый распространенный тип отношений в функционирующих приложениях ведения баз данных. Тому есть две причины. •
Почти всегда можно выразить отношение типа один-к-одному без использования двух таблиц. При этом быстродействие только повысится, хотя будет утрачена гибкость, предоставляемая хранением связанных данных в отдельной таблице. В предыдущем примере вместо создания отдельной таблицы с данными о видах работ можно поместить все поля, связанные с работой, в таблицу, предназначенную для хранения данных о сотрудниках.
• Выражение отношения один-ко-многим почти такое же простое для понимания (но гораздо более гибкое), как выражение отношения один-к-одному, поэтому сразу же переходим к следующему разделу.
Отношения типа один-ко-многим Гораздо чаще, чем отношения типа один-к-одному, в базах данных используются отношения типа один-ко-многим, в которых каждая запись таблицы связана с одной или несколькими записями в другой таблице (или вообще не связана ни с какими записями). В созданной ранее схеме базы данных между клиентами и заказами задано отношение один-ко-многим. Каждый клиент может иметь один или несколько заказов (или вообще не иметь заказов), поэтому между таблицами tblCustomers и tblOrder существует отношение один-ко-многим. Напомним, что для реализации такого отношения в базе данных копируется первичный ключ из таблицы на стороне "один" в таблицу на стороне "многие". В пользовательском интерфейсе для ввода данных этот тип отношения обычно имеет вид формы с основной (master) и подчиненной (slave) частями, в которой одна основная
Глава 1
запись отображается со своими подчиненными записями в отдельной части формы. В пользовательском интерфейсе первичный ключ из одной таблицы обычно связывается с внешним ключом из связанной таблицы с помощью списка или поля со списком.
Отношения типа многие-ко-многим Отношение типа многиеко-многим по сравнению с отношением один-ко-многим идет еще дальше. В качестве классического примера отношения типа многие-ко-многим можно привести отношение между студентами и классами. Каждый студент может иметь много классов, а каждый класс — много студентов. (Конечно же, возможны варианты, когда класс будет состоять из одного студента или в нем вовсе не будет ни одного учащегося, а также вполне возможно для студента иметь только один класс или ни одного.) В данном бизнес-примере отношение задается между заказами и позициями заказа, т.е. каждый заказ может содержать несколько позиций, а каждая позиция может присутствовать в нескольких заказах. Чтобы установить отношение многие-ко-многим, необходимо иметь три таблицы: две для хранения реальных данных и третью (именуемую соединительной) для хранения отношения между двумя первыми таблицами. Таблица соединения обычно состоит только из двух внешних ключей — по одному из каждой связанной таблицы, хотя иногда в таблице соединения полезно использовать собственное поле с идентификаторами для предоставления доступа к записям таблицы с помощью программных средств. В качестве примера отношения многие-ко-многим можно модифицировать пример из предыдущего раздела таким образом, чтобы в базе данных хранилось несколько позиций, связанных с одним заказом, т.е. у каждого заказа было много позиций и каждая позиция относилась к неограниченному количеству заказов. В этом случае таблицы могут выглядеть так, как показано на рис. 1.13. tbIOrderltem PK
tbtltem
• РК IE
Name Price Description
tbIOrder
Ш
FK1 OrderlD FK2 ItemID Quantity Cost
PK
Ш CustomerlD OrderDate Amount
РИС. 1.13. В этой группе таблиц, участвующих в отношении многие-ко-многим, tbIOrderltem является таблицей соединения
Создание пользовательского интерфейса на основе Windows Forms Разработчики предыдущих версий Visual Basic первыми предложили концепцию связывания данных, согласно которой связанный с данными объект или элемент управления данными (data control) позволяет программистам с минимальными усилиями
Основы построения баз данных
создавать простые, связанные с данными пользовательские интерфейсы. В Visual Basic .NET эта концепция также поддерживается, а многие недостатки прежней версии устранены. В прошлом разработчик мог установить связь между формой Visual Basic и базой данных с помощью элементов управления данными. Они предоставляют основные функции просмотра данных, позволяя приложению манипулировать наборами данных, вводить и обновлять их. На платформе .NET операциями подключения к базе данных и извлечения данных управляет автоматически созданный код, что позволяет добиться ряда преимуществ. 1. Автоматически созданный код, в отличие от абстрактного элемента управления данными, можно просматривать, поэтому он позволяет в большей степени контролировать способы доступа к данным. 2. Изучая автоматически созданный код, программист может познакомиться с классами платформы .NET, предназначенными для доступа к данным, что особенно полезно для тех, кто не имеет опыта работы на платформе .NET. 3. Основное назначение элементов управления данными в прежней версии Visual Basic — это подключение к базе данных, создание запроса к ней и управление данными. Теперь эти функции распределены между несколькими объектами, каждый из которых можно отдельно конфигурировать и использовать. В приведенных ранее примерах создана база данных, которая вполне подходит для ознакомления с основными принципами создания связанного с данными пользовательского интерфейса. В следующих разделах демонстрируются способы создания связанных с базой данных приложений на основе Windows Forms.
Подключение к базе данных и работа с записями Нет ничего проще, чем создать приложение на основе Windows Forms. И в этом заявлении нет никакого преувеличения; более того, если вас интересует лишь просмотр содержимого базы данных, вам вообще не придется писать ни единой строки кода. Весь процесс состоит из двух этапов: подключение к базе данных и связывание последнего пользовательского интерфейса с источником данных, генерированным Visual Studio .NET. Для этого выполните перечисленные ниже действия. 1. В Visual Studio .NET создайте новый проект на основе Windows Forms и откройте новую форму Forml. 2. В окне Server Explorer найдите созданную ранее таблицу tblCustomer и перетащите ее из окна Server Explorer в форму Forml. 3. После этого в нижней части окна с формой Forml появятся объекты SqlConn e c t i o n l и SqlDataAdapterl. Для извлечения и отображения данных используются три объекта: объект SqlConnectionl создает подключение к базе данных, объект-адаптер SqlDataAdapterl извлекает данные, а объект DataSet сохраняет данные, извлеченные адаптером SqlDataAdapterl. Для создания объекта DataSet выполните следующее.
Глава 1
1. Выберите команду меню DataO Generate Dataset (Данные1^ Генерация набора данных), и на экране появится диалоговое окно Generate Dataset. 2. Воспользуйтесь всеми заданными по умолчанию параметрами и щелкните на кнопке ОК. В результате будет создан новый объект DataSetll, который будет располагаться в нижней части окна под формой Forml возле объектов SqlConnectionlи SqlDataAdapterl. Для просмотра данных в форме создайте в форме элемент управления пользовательского интерфейса и свяжите его с только что созданным объектом DataSetll, выполнив перечисленные ниже действия. 1. Откройте панель элементов управления Toolbox с помощью команды меню View1^Toolbox (Просмотр^Панель инструментов управления), перейдите во вкладку Windows Forms и найдите элемент управления DataGrid (Сетка данных). Перетащите его в форму Forml, и в ней появится экземпляр DataGridl объекта DataGrid. 2. Свяжите этот элемент управления с источником данных. Для этого с помощью команды меню ViewOProperties Window (Просмотр1^Окно свойств) откройте окно свойств Properties и выберите для свойства DataSource (Источник данных) сетки DataGridl источник данных DataSetll. Затем выберите для свойства DataMember (Элемент данных) сетки DataGridl таблицу tblCustomer. 3. Наконец, создайте код извлечения данных из базы данных и вставки их в сетку DataGridl. Для этого дважды щелкните на форме, и в окне просмотра кода автоматически появится процедура Forml_Load. Введите в ней следующий код: Private Sub Forml_Load(ByVal sender As System.Object,_ ByVal e As System.EventArgs) Handles MyBase.Load SqlDataAdapterl.Fill(DataSetll) End Sub 4. Запустите полученное приложение с помощью команды меню DebugO Start (ОтладкаО Запуск), и в окне приложения будут отображены данные из таблицы tblCustomer. Здесь следует отметить одну особенность данного приложения. Все внесенные в нем изменения данных не будут отражены и сохранены в базе данных. Для их сохранения нужно создать дополнительный код вызова метода объекта DataAdapter. Эта тема рассматривается далее, в разделе об обновлении записей.
Создание приложения для просмотра данных В предыдущем примере показан простейший способ связывания данных на основе извлечения всей таблицы и отображения ее в элементе управления DataGrid. А как отобразить только одну запись? Для этого потребуется использовать элементы управления TextBox и Button, а также создать дополнительный код. Чтобы создать приложение для просмотра данных по одной записи из таблицы tblCustomer, выполните ряд действий.
Основы построения баз данных
1. В Visual Studio .NET создайте новый проект на основе Windows Forms и откройте новую форму Forml. Создайте в ней два текстовых поля, txtFirstName и txtLastName, на основе элемента управления TextBox. 2. Создайте объекты SqlConnection, Sql Data Adapter и DataSet для извлечения данных о клиентах из таблицы tblCustomer. (Необходимые для этого действия аналогичны действиям из предыдущего примера.) Как и прежде, не забудьте вызвать метод Fill объекта SqlDataAdapter в коде для инициализации объекта DataSet. (В данном примере объект DataSet имеет имя DsCustomerl. — Прим. ред.) 3. Теперь нужно создать связь между двумя текстовыми полями (txtFirstName и txtLastName) и соответствующими полями в базе данных. Для этого щелкните на текстовом поле txtFirstName и в группе свойств Data выберите подгруппу свойств (DataBindings). Это свойство содержит несколько свойств, которые следует установить для связывания данных таблицы с текстовым полем. 4.
Выберите поле FirstName таблицы tblCustomer для свойства Text текстового поля txtFirstName. Для этого щелкните в правой части поля со списком возле свойства Text. Выберите набор данных DsCustomerl, таблицу tblCustomer и поле FirstName, как показано на рис. 1.14. IxtFirstName System,Windows.Forms.TextBox :
?-. ГШПйП ' '; ЯШШВИЯ Tag ffl (DynamicPropertiss) !:; :V (Name) ;| AcceptsReturn AcceptsTab AccessibleDescription Я AccessbleName : AccessbteAole AllowOrop =>| Anchor SjAutoSze sJBackColor ji|Border5tyle Text
(None) В И DsCustomerl • В Ш tblCustomer
1
i ИI CO LastName [^ ГЛ| Company Л
Default Talse Top, Left True I | Window Fixed3D
РИС. 1.14. Создание связи между данными из поля базы, данных и текстовым полем с помощью свойств (DataBindings)
5. Аналогично свяжите текстовое поле txtLastName с полем LastName таблицы tblCustomer. 6. Запустите приложение, в текстовых полях которого будут отображены имя и фамилия первого клиента. Возможности этого приложения весьма ограниченны, потому что в нем можно просматривать только по одной записи и нельзя редактировать данные. Однако оно является базовым приложением, на основе которого будут созданы несколько других примеров с более широкими возможностями рабочего приложения для полномасштабной работы с базами данных.
Глава 1
Даже в таком ограниченном примере очевидны преимущества способов связывания данных на платформе .NET: они более гибки, чем аналогичные способы в Visual Basic 6. Например, упомянутая гибкость достигается за счет способности управлять процессом связывания с помощью кода. Попробуем теперь создать код для перехода от одной записи к другой с помощью перечисленных ниже действий. 1. Создайте две кнопки, btnNext и btnPrevious, для перехода к следующей и предыдущей записям. 2. Дважды щелкните на кнопке btnNext и в автоматически появившемся окне редактирования кода с определением процедуры btnNext_Click вставьте следующий код: Private Sub btnNext_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNext.Click Me.BindingContext(DsCustomerl, "tblCustomer").Position += 1 End Sub
3. Дважды щелкните на кнопке btnPrevious и в автоматически появившемся окне редактирования кода с определением процедуры btnPrevious_Click вставьте код Private Sub btnPrevious_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrevious.Click Me.BindingContext(DsCustomerl, "tblCustomer").Position —= \ End Sub
4. Снова запустите приложение и убедитесь в том, что с помощью созданных кнопок можно переходить к следующей и предыдущей записям. (Учтите, что эта программа будет работать только при наличии нескольких записей в таблице.) Объект BindingContext предоставляет средства организации перехода к другим записям в приложении для работы с данными. При создании таких приложений в предыдущих версиях Visual Basic для организации переходов к другим записям требовалось использовать элемент управления Data. На платформе .NET выделен, специальный объект BindingContext, который отвечает за связывание данных. (Иными словами, выделение небольшого специализированного объекта из более крупного общего объекта позволяет распределить специализированные функции среди нескольких объектов меньшего размера.) В объектно-ориентированном программировании разработчик стремится создавать специализированные объекты, чтобы упростить структуру программы и сделать ее более гибкой. Таким образом, при создании приложения, рассчитанного на работу с базами данных, для составления запросов, обновления данных, связывания элементов управления пользовательского интерфейса с данными и перехода к полям таблицы не рекомендуется использовать один громоздкий объект Data. Вместо него в Windows Forms и ADO.NET предусмотрено несколько отдельных специализированных объектов. Выделение функций доступа к данным — ключевое достоинство платформы .NET Framework (этот вопрос подробно рассматривается в следующих главах). Объект BindingContext является членом семейства объектов Windows Forms (а точнее, членом пространства имен System. Windows. Forms платформы .NET Framework) и содержит множество полезных свойств и методов. Например, объект
Основы построения баз данных
BindingContext можно использовать для определения количества записей в источнике данных так, как описано ниже. 1. Создайте ярлык IblDataStatus с помощью элемента управления Label с пустой строкой в свойстве Text. 2. В коде формы создайте подпрограмму ShowDataStatus с указанным ниже кодом, которая будет отображать текущее расположение записи и общее количество записей в ярлыке IblDataStatus. Private Sub ShowDataStatus() With Me.bindingContext(DsCustomerl, "tblCustomer") IblDataStatus.Text = "Record " s .Position + 1 & " of " & .Count End With End Sub
3. Поместите вызов этой подпрограммы ShowDataStatus ( ) в подпрограммы обработки событий загрузки формы (Forml_Load) и щелчков мыши на обеих кнопках (btnNext_Click и btnPrevious_Click). Это позволит отображать обновленную информацию о текущем количестве записей и текущей записи при загрузке формы и после каждого перемещения к другой записи. Учтите, что отсчет текущего номера записи (свойство Position объекта DataBindings) начинается с нуля (как и во всех коллекциях на платформе .NET). Поэтому для получения реального номера записи следует прибавить к нему 1. 4. Запустите приложение и попробуйте перейти к разным записям таблицы. Тогда в ярлыке будет отображено общее количество записей в таблице и номер текущей записи.
Программный способ связывания данных С помощью Windows Forms связывание данных можно организовать программно. Это позволяет добиться более высокой гибкости в ситуациях, когда расположение полей неизвестно во время создания приложения либо требуется явно выразить связь между элементами управления и полями другим способом, чем предлагается в интегрированной среде разработки. Чтобы организовать связь с элементами управления пользовательского интерфейса, следует создать метод Add объекта DataBindings элемента управления Windows Forms. В листинге 1.1 показан типичный способ создания связи с данными в приложении для работы с базами данных. Листинг 1.1. Программный способ очистки и установления связи с данными Private Sub Forml_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load txtFirstName.DataBindings.Clear() txtLastName.DataBindings.Clear() txtFirstName.DataBindings.Add("Text", DsCustomerl, "tblCustomer.LastName") txtLastName.DataBindings.Add("Text", DsCustomerl, "tblCustomer.LastName") sqlAdapterl.Fill(DsCustomerl) ShowDataStatus() End Sub
Глава 1
(Убедитесь в том, что для свойства ConnectionString объекта SqlConnectionl задана верная строка подключения с используемым вами сервером SQL Server. Дело в том, что в коде этого примера, который можно скопировать по адресу: h t t p : / / www.williamspublishing.com, указана строка подключения к серверу SQL Server, установленному на компьютере ROCKO автора книги. — Прим. ред.) Обратите внимание, что вызовы метода Clear элементов управления коллекции DataBindings не обязательно создавать в разрабатываемом приложении. Они нужны в этом случае, потому что связь с данными ранее задана с помощью окна Properties. Метод Add коллекции DataBindings принимает три параметра: свойство элемента управления, с которым связываются данные; объект источника данных (обычно, но не обязательно объект DataSet), ссылка на член источника данных, который предоставляет данные. После запуска приложения с приведенным выше кодом для метода Load в поле с именем клиента будет отображена его фамилия, а в поле с фамилией — его имя.
Элементы управления, взаимодействующие с данными Элементом управления, взаимодействующим с данными (data-aware control), может быть любой элемент управления, имеющий свойство-коллекцию DataBindings. С помощью этого свойства можно ссылаться на любой тип данных, включая реляционные источник данных. Свойство DataBindings соединяет элемент управления пользовательского интерфейса с элементом управления данными (т.е. именно так происходит связывание пользовательского интерфейса с базой данных). Поэтому говорят, что элемент управления пользовательского интерфейса связан с базой данных через элемент управления данными. В предыдущих версиях Visual Basic с источником данных можно было связать относительно небольшое количество элементов управления пользовательского интерфейса. Возможности манипулирования связанными с данными элементами управления были довольно ограниченными: пользователь мог связать их с теми источниками данных, для которых существует провайдер данных ADO. Для взаимодействующих с данными элементов управления разработчику приходилось создавать рутинный код большого размера для выполнения вручную всех операций связывания данных. На платформе .NET практически каждый элемент управления Windows Forms может быть связан с данными, включая сложные элементы управления, например TreeView. Более того, разработчик не ограничен только реляционными источниками данных или известными среде Visual Studio .NET или ADO.NET. Любой объект, реализующий интерфейс IList, может быть связан с данными, включая наборы данных DataSet и более сложные конструкции, например массивы и коллекции.
Обновление записей в приложении просмотра данных До сих пор в приведенных ранее примерах нам удавалось только извлекать и просматривать данные. А изменять данные можно было только в элементах пользовательского интерфейса, но их нельзя было сохранить (зафиксировать) в базе данных.
Основы построения баз данных
Интуитивно понятно, что изменения в связанном с данными элементе управления пользовательского интерфейса должны автоматически сохраняться в базе данных. Именно так работают различные связанные с данными элементы управления пользовательского интерфейса в прежних версиях Visual Basic. Почему же в Windows Forms на платформе .NET связывание с данными организовано иначе? Принудительная фиксация обновлений в источнике данных с помощью дополнительной строки кода продиктована требованиями гибкости и более высокой производительности. Рассмотрим принцип работы объекта DataSet на платформе .NET. На рис. 1.15 показана схема взаимосвязи между формой, объектом DataSet и базой данных в приложении на основе Windows Forms. 1 Windows Forms Applications j Brad
Таблица tbICustomer
r
^^
База данных
j Jones Previous j
I^H
Next
j
РИС. 1.15. Схема взаимосвязи между связанной формой, объектом DataSet и базой данных
В созданном ранее приложении все данные в исходном состоянии находятся в базе данных. Затем они извлекаются и сохраняются в памяти в объекте DataSet. Форма содержит элементы управления, связанные с полями таблицы в объекте DataSet. Форма обнаруживает появление новых данных и автоматически отображает содержимое полей в связанных с данными элементах управления. В связанном с данными приложении изменение содержимого связанного с данными элемента управления влияет только на объект DataSet, т.е. изменение содержимого текстового поля приводит к изменению содержимого записи в таблице, которая находится в объекте DataSet. Но изменение объекта DataSet не копируется в базу данных, а сохраняется до тех пор, пока не поступит явное указание скопировать их в базу данных (с помощью метода Update набора данных DataSet). Хотя явное включение этой инструкции может показаться излишним (ведь в прежних версиях Visual Basic этого делать было не нужно), но на самом деле оно позволяет добиться более высокой производительности. Дело в том, что в таком случае приложению не нужно постоянно поддерживать соединение с базой данных во время редактирования данных пользователем. В листинге 1.2 показан пример модифицированных обработчиков событий, которые позволяют редактировать данные в созданном ранее приложении. Листинг 1.2. Сохранение данных с помощью явного обновления объекта DataSet при перемещении пользователя к другим записям Private Sub btnNext_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bfnNext.Click Me.BindingContext(DsCustomerl, "tbICustomer").Position += 1 SqlDataAdapter1.Update(DsCustomerl) ShowDataStatus() End Sub
Глава 1 Private Sub btnPrevious_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrevious.Click Me.BindingContext(DsCustomerl, "tblCustomer").Position —= 1 SqlDataAdapterl.Update(DsCustomerl) ShowDataStatus() End Sub
Конечно, обновлять каждую запись при перемещении пользователя к другим записям совсем не обязательно. Поскольку разработчик может контролировать способ обновления объекта DataSet, можно было бы организовать обновление внесенных изменений с помощью специальной кнопки или команды меню Save. Можно также отложить фиксацию обновлений до окончания редактирования группы строк, т.е. использовать пакетное обновление. В ADO.NET для пакетного обновления не нужно создавать какой-либо иной специализированный код, потому что оно выполняется автоматически объектами DataSet (который сохраняет данные в памяти) и SqlDataAdapter (который отвечает за выполнение необходимых команд управления базой данных для гарантированного корректного представления, вставки, обновления и удаления данных). Более подробно связь между этими объектами описывается в главах 5, "ADO.NET: объект DataSet", и 6, "ADO.NET: объект DataAdapter".
Создание новых записей в форме, связанной с данными Для создания новой записи в связанном с данными приложении на основе Windows Forms нужно использовать метод AddNew объекта BindingContext. При выполнении этого метода любые связанные с данными элементы управления очищаются для ввода новых данных. После ввода новых данных они фиксируются в базе данных с помощью метода Update объекта DataAdapter (как в предыдущем примере). Для создания новых записей в связанном с данными приложении выполните перечисленные ниже действия. 1. Создайте в форме новую кнопку с именем btnNew и укажите значение New (Ввести новые данные) для ее свойства Text. 2. Щелкните дважды на кнопке и введите приведенный ниже код обработки события щелчка на этой кнопке. Private Sub btnNew_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNew.Click Me.BindingContext(DsCustomerl, "tblCustomer").AddNew() txtFirstName.Focus() ShowDataStatus()
End Sub
3. Запустите приложение и щелкните на кнопке New. После очистки текстового поля пользователь сможет ввести в форме новую запись. Для сохранения новой записи нужно перейти к другой записи с помощью кнопок Next или Previous. Учтите, что кнопки Next или Previous фиксируют обновления объекта DataSet, поэтому в данном примере не нужно использовать явные инструкции обновления объекта DataSet после создания новой записи. В данном случае достаточно просто перейти к другой записи. Но если пользователь закроет приложение до фиксации новых дан-
Основы построения баз данных
ных в базе данных (либо неявно с помощью перехода к другой записи, либо явно с помощью метода Update объекта DataAdapter), то новые данные будут утрачены. Кроме того, пользователю обычно предоставляют возможность отмены внесенных изменений с помощью метода CancelCurrentEdit объекта BindingContext.
Удаление записей из связанной с данными формы Для удаления записей из связанной с данными формы на основе Windows Forms нужно использовать метод RemoveAt объекта BindingContext. Этот метод принимает один параметр — индекс удаляемой записи. Для организации удаления текущей записи нужно использовать свойство Position в качестве параметра метода RemoveAt объекта BindingContext, как показано в листинге 1.3.
Листинг 1.3. Удаление данных в приложении для работы с данными с ПОМОЩЬЮ Метода RemoveAt Объекта BindingContext Private Sub btnDelete_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDelete.Click If MsgBox("Whoa bubba, you sure?", MsgBoxStyle.YesNo, "Delete record") = MsgBoxResult.Yes Then W i t h Me.BindingContext(DsCustomerl, "tblCustomer") .RemoveAt(.Position) End W i t h End If End Sub Этот код основан на созданной перед этим кнопке btnDelete. Учтите, что эта процедура запрашивает пользователей, действительно ли они хотят удалить запись. Этот запрос позволяет избежать неприятных последствий в случае, если пользовательский интерфейс создан так, что пользователь может случайно удалить запись, щелкая на кнопке Delete. (Обратите внимание, что, кроме этого способа на основе диалогового окна с предупреждением об удалении записи, можно применять более сложные методы отката ошибочных изменений данных. Однако описание таких сложных конструкций выходит за рамки данной главы.) Учтите, что метод RemoveAt способен определять и обрабатывать стандартные исключительные ситуации, например при отсутствии данных или после очистки данных в элементе управления пользовательского интерфейса при вызове метода AddNew. Эта возможность позволяет значительно усовершенствовать методы контроля над связанными с данными элементами управления в прежних версиях Visual Basic, для которых требовалось создавать громоздкий код обработки исключительных ситуаций, возникающих при выполнении пользователями непредсказуемых действий.
Проверка введенных данных в форме, связанной с данными В программировании баз данных проверка введенных данных (validation) гарантирует, что эти данные отвечают правилам, определенным при проектировании приложе-
Глава 1
ния. Эти правила называются правилами проверки данных (validation rules). Один из способов проверки данных при программировании приложения на основе Windows Forms состоит в написании кода для события RowUpdating объекта DataAdapter. Событие RowUpdating возникает как раз перед обновлением записи, а событие RowUpdated— сразу после обновления записи. Размещая код проверки введенных данных в событие RowUpdating, можно быть уверенным в том, что будут обрабатываться любые изменения данных в любой части приложения. Ключевым фактором эффективного использования события RowUpdating является использование свойств и методов аргумента события, который представлен в виде экземпляра объекта System.Data.SqlClient.SqlRowUpdatingEventArgs. Кроме проверки команды обновления записи (с помощью свойства Command объекта), можно проинформировать адаптер данных DataAdapter об отказе от обновления и откате внесенных изменений. В листинге 1.4 этот подход иллюстрирует рассмотренный ранее пример приложения для просмотра данных.
Листинг 1.4. Построчная проверка введенных данных с помощью события RowUpdating Объекта DataAdapter Private Sub SqlDataAdapterl_RowUpdating(ByVal sender As Object, ByVal e As System.Data.SqlClient.SqlRowUpdatingEventArgs) Handles SqlDataAdapterl.RowUpdating If e . R o w . I t e m ( " F i r s t N a m e " ) = "" Or e . R o w . I t e m ( " L a s t N a m e " ) = "" Then MsgBox("Change not saved; customer must have a f i r s t and last name.") e.Status = UpdateStatus.SkipCurrentRow e . R o w . R e j ectChanges() End If End Sub Передача значения UpdateStatus . SkipCurrentRow свойству Status аргумента события позволяет сообщить адаптеру данных о прекращении операции, т.е. отмене обновления данных, потому что оно не прошло проверку. Но недостаточно просто прекратить выполнение операции, потому что в этом случае пользователь получит пустое текстовое поле (и пустое поле в объекте DataSet). Для решения этой проблемы следует вызвать метод Re j ectChanges объекта Row, который содержится в аргументе события. Он обновит содержимое пользовательского интерфейса и сообщит объекту DataSet о том, что больше не нужно согласовывать эту строку с базой данных. После этого можно продолжать редактирование данных, не беспокоясь об их безопасности.
Проверка введенных данных на уровне процессора баз данных Помимо проверки данных во время ввода информации, следует знать о том, что можно также выполнять проверку и на уровне процессора баз данных. Такая проверка обычно более надежна, поскольку применяется независимо от причины изменения данных. При этом вам не нужно заботиться о реализации правил проверки введенных данных в каждом приложении, которое получает доступ к какой-нибудь таблице. Однако проверка введенных данных на уровне процессора баз данных отличается
Основы построения баз данных
меньшей гибкостью, поскольку его практически невозможно переопределить, и часто имеет примитивную форму (обычно ограничивается тем, что не допускает ввод в поля пустых значений). Кроме того, проверку введенных данных на уровне процессора баз данных можно выполнять только на уровне поля, и вы не сможете сделать так, чтобы правила проверки введенных данных, реализуемые процессором баз данных, были основаны на сравнении значений двух полей (если только проверка не реализована на основе ограничения первичный/внешний ключ или реализована в серверной процедуре в виде триггера). Контроль на уровне процессора баз данных является функцией схемы базы данных. Предположим, вы хотите быть уверены в том, что ни одна запись о клиенте не будет введена в таблицу tblCustomer без указания его имени и фамилии. Тогда установите правило проверки введенных данных на уровне процессора баз данных, выполнив перечисленные ниже действия. 1. В окне Server Explorer среды Visual Studio .NET откройте схему таблицы tblCustomer. 2. В столбце Allow Nulls (Допускаются неопределенные значения) снимите флажки FirstName и LastName. 3. Сохраните схему таблицы tblCustomer с помощью команды меню File^Save tblCustomer. Теперь никакое программное обеспечение, использующее эту базу данных, не сможет ввести запись о клиенте без указания его имени и фамилии. (Любая попытка приведет к возникновению исключительной ситуации.)
Резюме Эта глава посвящена основам баз данных в целом, а также простейшим способам соединения приложений Visual Basic .NET для работы с данными, хранящимися в базе данных SQL Server. Следует учитывать, что правильно составленная схема базы данных может значительно повысить производительность и практичность приложения. Нормализация, ссылочная целостность и индексирование могут оказаться весьма эффективными для достижения этих целей. Однако помните, что чрезмерное индексирование может привести к обратному эффекту и замедлить работу приложения. В следующих главах приводятся примеры бизнес-ситуаций, в которых следует учитывать эти особенности.
Вопросы и ответы Существует ли в Visual Studio .NET элемент управления Data, который в Visual Basic б можно было успешно использовать для быстрого создания прототипов данных? Нет. Все функции элемента управления Data, который использовался в Visual Basic 6 и более старых версиях, теперь распределены среди разных объектов данных. Например, соединение с базой данных теперь создается с помощью отдельного объекта SqlConnection, операции извлечения, обновления и удаления данных— с по-
Глава 1
мощью объектов BindingContext и DataAdapter, а операции перемещения по записям— с помощью объекта BindingContext. В отличие от прежних объектов для работы с данными, новые объекты не имеют никакого визуального представления во время выполнения, что позволяет разработчику создавать практически любые виды пользовательского интерфейса для работы с данными. Можно ли первичный ключ составить из нескольких полей? Да, хотя такие ключи встречаются нечасто. Они называются конкатенированными ключами. Например, если вы составляете конкатенированный первичный ключ из полей, содержащих имя и фамилию, то это значит, что в такой базе данных нельзя зарегистрировать полных "тезок", поскольку каждое сочетание имени и фамилии должно образовывать уникальное значение.
Запросы и команды на языке SQL
В ЭТОЙ ГЛАВЕ.. Что такое запрос Тестирование запросов с помощью компонента Server Explorer Отбор записей с помощью предложения SELECT Указание источника записей с помощью предложения FROM Формирование критериев с использованием предложения WHERE Сортировка результатов с помощью предложения ORDER BY Отображение первых или последних записей диапазона с помощью предложения ТОР Объединение связанных таблиц в запросе Выполнение вычислений в запросах Определение псевдонимов с использованием предложения AS Запросы, которые группируют данные и подводят итоги Запросы на объединение Подзапросы Манипулирование данными с помощью SOL Использование языка определения данных Резюме Вопросы и ответы
Глава 2
В главе 1, "Основы построения баз данных", где демонстрируется создание базы данных с помощью Visual Studio .NET и SQL Server, вы познакомились со структурой базы данных и ее таблиц. В настоящей главе основное внимание уделяется манипулированию данными в таблицах, а также созданию и модификации структуры таблиц с помощью языка структурированных запросов (Structured Query Language — SQL). Благодаря запросам SQL пользователь может выбирать записи из таблицы базы данных, находить связанные с ними данные в других таблицах и манипулировать структурой баз данных. Кроме того, запросы SQL вполне применимы для манипулирования базами данных в программах. Язык SQL представляет собой стандартный способ управления базами данных. Он реализован в различных формах многими производителями в системах реляционных баз данных, включая Microsoft Access и SQL Server, а также системы, созданные другими поставщиками программного обеспечения, например Oracle и IBM. (Язык SQL обязан своим происхождением разработчикам компании IBM.) Как правило, SQL используется для создания запросов, которые извлекают данные из баз данных, хотя множество команд SQL выполняют и другие действия, например создание таблиц и полей. Команды SQL делятся на две категории: •
команды языка определения данных (Data Definition Language- DDL), которые позволяют использовать запросы SQL для создания таких компонентов баз данных, как таблицы, поля и индексы;
•
команды языка манипулирования данными (Data Manipulation Language- DML), которые позволяют извлекать, создавать, удалять и обновлять записи в базе данных.
В этой главе рассматриваются способы использования обеих категорий команд SQL.
Что такое запрос Запрос (query) — это команда базы данных, осуществляющая выборку записей. Используя запросы, можно получить данные из одного или нескольких полей, принадлежащих одной или нескольким таблицам. При этом данные можно отбирать в соответствии с определенными условиями, называемыми критериями, которые служат для ограничения общего объема отбираемых данных. Запросы в Visual Basic .NET обычно основаны на SQL. Это стандартный язык для осуществления выборки информации и других операций над базами данных. Он прост в освоении и реализован во многих различных базах данных, поэтому при желании преобразовать свое приложение управления базой данных SQL Server, например, в Sybase или Oracle вам не придется заново изучать совершенно новый язык запросов. Однако все это теория. А на практике каждый производитель базы данных имеет собственный способ реализации стандарта (так называемый промышленный стандарт), и Microsoft в этом смысле не является исключением. Хотя реализация SQL в СУБД SQL Server радикально не отличается от реализаций прочих производителей, вы должны знать, что существуют и другие диалекты языка SQL. В частности, раз-
Запросы и команды на языке SQL
работнику с опытом работы с Microsoft Access при знакомстве с СУБД SQL Server придется столкнуться с множеством различий в синтаксисе SQL, которые подробно рассматриваются далее.
Тестирование запросов с помощью компонента Server Explorer Компонент Server Explorer среды Visual Studio .NET — это полезный инструмент для опробования концепций, описанных в этой главе. С помощью перечисленных ниже действий создайте тестовое представление данных в окне компонента Server Explorer, которое можно будет использовать для тестирования запросов SQL, предлагаемых далее в главе. Для выполнения примеров данной главы необходимо иметь доступ к SQL Server. (Подробно процесс инсталляции и запуска SQL Server описан в главе 3, "Знакомство с SQL Server 2000".) Далее в этой главе предполагается, что вы уже установили SQL Server и включили его в окно Server Explorer, как описано в главе 1, " Основы построения баз данных". Для создания тестового представления данных в окне Server Explorer среды Visual Studio .NET выполните ряд действий. 1. В среде Visual Studio .NET создайте новый проект на основе Windows Forms. 2. В окне Server Explorer найдите SQL Server и разверните папку созданной ранее базы данных Novelty. Эта папка содержит несколько объектов, например схем баз данных, таблиц и представлений. 3. Щелкните правой кнопкой мыши на папке с представлениями Views и выберите в контекстном меню команду New View (Новое представление). 4. В диалоговом окне Add Table (Создать таблицу) выберите таблицу tblCustomer и щелкните на кнопке Add (Создать). После этого структура созданной таблицы появится в окне конструктора представления. 5. Щелкните на кнопке Close для закрытия диалогового окна Add Table. На экране появится окно конструктора представления, состоящего из четырех панелей: структур, полей, запросов SQL и результатов (рис. 2.1). 6. Отметьте поля FirstName, LastName и Address в таблице tblCustomer. По мере выбора полей для создания запроса будут изменяться панели полей и запросов SQL. 7. Выберите команду меню QuetyORun (ЗапросОЗапуск), и нижняя панель результатов выполнения запроса будет иметь вид как на рис. 2.2. Созданный запрос можно сохранить для последующего использования. Сохраненные в базе данных запросы называются представлениями (views). Их можно использовать точно так же, как обычные таблицы базы данных. Они позволяют упростить работу со сложными базами данных, особенно если запросы включают несколько соединенных таблиц (как будет показано далее в главе).
Глава 2
Лю.Уреи! : VL..ROCt:0.noYdty)* |
t "louSut' IsortType
:
• > ; : • •' i ' ISortOfdef
[crieria'
1
РИС. 2.1. Диалоговое окно режима создания представления
(Д1 Columns) ГО RrstName LaslNarne Company Address City State PostaKcde Phone
[Output [Sort Type tbrCustomer tbCustomer tbrCustomer
RrstName LastName Address
FrstName, LastName, Address novelty. dbo. tbICustomer HrstName
ll.astName 123 Main Street 4S6 Elm Lane 789 27th Street 1184 Centre Street 9904 Anywhere Place 4475 Elm Street 8339 Agate Street 4905 Brown Valley Lane
РИС. 2.2. Диалоговое окно режима создания представления после запуска запроса
Запросы и команды на языке SQL
Для сохранения представления в среде Visual Studio .NET выберите команду меню File^Save View"!, и Visual Studio .NET предложит ввести новое имя для данного представления. Укажите для него имя qryCustomerList. После этого представление будет сохранено в базе данных и его могут использовать другие разработчики, которым нужно получить доступ к базе данных.
j Вы уже, наверное, заметили, что для таблиц и представлений используется простое j соглашение об именах, основанное на присвоении префиксов tbl и qry именам j | объектов базы данных. Тому есть две причины. Во-первых, это упрощает определе! ние типа объекта базы данных, потому что в некоторых ситуациях это может быть не • совсем очевидно. Во-вторых, такое соглашение об именах использовалось в прежj них изданиях этой книги и поддерживается здесь для преемственности. | Наше соглашение об именах уже знакомо программистам, которые имеют опыт ра| боты с Microsoft Access. Хотя представленные здесь действия выполняются несколь\ ко иначе, чем к тому привыкли программисты, имеющие опыт работы с SQL Server, I мы считаем, что наличие какого-либо соглашения об именах все же лучше, чем его > j отсутствие. Конечно, в своей работе вы можете использовать какое-то другое со- j ! глашение об именах. L...,
„„.._„
V,
.
.
.
,, .
...
...
.
..,
..'.... .'..'/...^
;,;•'
В следующих разделах диалоговое окно режима создания представления будет использовано для создания запросов на выборку данных.
Отбор записей с помощью предложения SELECT Предложение SELECT является основой каждого запроса, предназначенного для выборки данных. Оно указывает процессору баз данных, какие поля требуется возвратить. Общая форма предложения SELECT имеет следующий вид: SELECT *
А его содержание таково: "Вернуть значения всех полей, найденных в указанном источнике записей". Эта форма команды удобна тем, что вам не обязательно знать имена извлекаемых полей таблицы. Однако выборка всех полей таблицы может быть не рациональной, особенно в том случае, когда требуется только два поля, в то время как такой запрос осуществляет выборку двух десятков полей. Кроме команды, передаваемой процессору базы данных на возврат всех полей источника записей, можно задать конкретный перечень необходимых при отборе полей. Такое ограничение может улучшить эффективность выполнения запроса, особенно для больших таблиц, содержащих много полей, так как в этом случае отбираются только нужные поля. Ниже приводится пример предложения SELECT, которое извлекает из базы данных значения только двух полей таблицы— FirstName и LastName, содержащих имя и фамилию клиента. SELECT [FirstName], [LastName]
Глава 2
Обратите внимание также на то, что предложение SELECT не готово к выполнению без предложения FROM (поэтому примеры предложения SELECT, приведенные в этом разделе, выполнить в таком виде нельзя). Чтобы полнее ознакомиться с предложениями SELECT, просмотрите примеры использования предложения FROM, приведенные в следующем разделе.
Указание источника записей с помощью предложения FROM Предложение FROM указывает на источник записей, из которого запрос извлекает записи. Этим источником может быть как таблица, так и другой хранимый запрос. У вас также есть возможность отбора записей из нескольких таблиц, которая подробно рассматривается далее, в разделе об объединении нескольких таблиц в одном запросе. Предложения FROM работают совместно с предложениями SELECT. Например, чтобы отобрать все записи в таблице tblCustomer, используйте приведенную ниже команду SQL. SELECT *
FROM tblCustomer
При выполнении этого запроса считываются все записи и все поля в таблице tblCustomer (без какого-либо упорядочения записей). Чтобы отобрать только имя и фамилию клиентов, воспользуйтесь приведенной ниже командой SQL. SELECT FirstName, FROM tblCustomer
LastName
После изменения запроса в режиме конструктора представления выберите команду Query^Run (ЗапросОЗапуск) для обновления результатов выполнения запроса, которые теперь будут иметь такой вид, как на рис. 2.3. РИС. 2.3. Результаты выполнения запроса на выборку данных из полей FirstName и LastName таблицы tblCustomer
\ FirstName 1 LastName
tbCuslomer tblCustomer
Ft ifjarru i istNai » novelty. dbo.tbtoistomer FirstName John Jill Brad Daisy Dave Betty Thurston Jane
5m*h Azala Jones Klein • Martin Klein Ryan Writers
Из соображений эффективности всегда ограничивайте число полей в предложении SELECT только теми полями, которые могут потребоваться вашему приложению. Обратите внимание, что записи, отобранные запросом SELECT FROM, в результирующем наборе не упорядочены. Если не задать порядок сортировки (использование предложения ORDER BY рассматривается ниже в этой главе), записи всегда возвращаются в неопределенном порядке.
Запросы и команды на языке SQL
Формирование критериев с использованием предложения WHERE Предложение WHERE указывает процессору базы данных на необходимость ограничения количества отбираемых записей согласно одному или нескольким заданным критериям. Критерий— это логическое выражение, результатом оценки которого является либо "истина" (true), либо "ложь" (false). В языке SQL существует много аналогичных выражений эквивалентности, знакомых пользователям Visual Basic (например: >0 и = ' Smith'). Предположим, вам нужно отобрать только тех заказчиков, которые проживают в Калифорнии (СА). Для этого можно использовать приведенный ниже запрос SQL. SELECT FirstName, LastName, State FROM tblCustomer WHERE State = 'CA'
В результате выполнения этого запроса будет извлечена запись с данными о клиенте с именем Daisy Klein. Обратите внимание также на то, что для обозначения текстовой строки в предложении WHERE используется одиночная кавычка. Подобное обозначение удобно тем, что отличается от обозначения текстовой строки в Visual Basic двойной кавычкой, а инструкции SQL иногда встраиваются в код Visual Basic. Можно создавать более сложные предложения WHERE, связывая два и более критерия с помощью логических операторов AND или OR. Например, необходимо отобрать всех клиентов, проживающих в городе Денвер (Denver) штата Колорадо (СО), т.е. вас не интересуют те клиенты, которые проживают в других городах этого штата. Для этого нужно задать два критерия и связать их оператором AND, как показано в приведенном ниже примере. SELECT FirstName, LastName, City, State FROM tblCustomer
WHERE (State = ' C O ' ) AND (City = ' D e n v e r ' ) В результате выполнения этого запроса будет извлечена запись с данными о клиенте с именем Thurston Ryan, который живет в городе Денвер, штат Колорадо. Если в этом городе живут другие клиенты, то в результате выполнения данного запроса будут извлечены записи с информацией о них. Однако при этом не будут извлекаться сведения о клиентах, которые проживают в городах с тем же названием, но в других штатах. Если вас интересует информация о клиентах в штатах Вашингтон (WA) и Калифорния (СА), воспользуйтесь оператором OR, чтобы связать два критерия, как показано ниже. SELECT FirstName, LastName, City, State FROM tblCustomer WHERE State = 'CO' OR State = 'CA'
В результате выполнения этого запроса будут извлечены три записи с данными о клиентах в штатах Вашингтон и Калифорния. Из сказанного выше следует, что для от-
Глава 2
бора данных из таблицы с помощью условий AND и OR можно составить практически любую комбинацию критериев в предложении WHERE.
Ключ к успешной разработке приложений клиент/сервер — выработка такой тактики, | согласно которой приложение-клиент не заказывало бы слишком много записей в I одной выборке. Это гарантирует, что приложения будут выполняться быстро и компьютеры ваших пользователей не зависнут. Залог успеха вашей работы — рациональное использование предложения WHERE.
Операторы, используемые в предложении WHERE При построении предложения WHERE можно использовать операторы, перечисленные в табл. 2.1.
Таблица 2.1. операторы, используемые в предложении WHERE Оператор
Функция Меньше Меньше или равно Больше Больше или равно Равно Не равно
BETWEEN
Внутри диапазона значений
LIKE IN
Соответствует образцу Входит в список значений
Оператор BETWEEN Этот оператор возвращает все записи, значения которых лежат внутри определенных вами границ. Например, для того чтобы отобрать все заказы, оформленные за период с 4 января по 5 июня 2001 года, необходимо написать приведенную ниже инструкцию SQL. SELECT *
FROM tblOrder WHERE OrderDate BETWEEN ' 1 / 4 / 2 0 0 1 ' AND ' 6 / 5 / 2 0 0 1 ' В результате выполнения этого запроса будут извлечены записи, показанные на рис. 2.4. Обратите внимание, что значения даты в SQL Server обозначаются символом одиночной кавычки. Разработчикам, которые имеют опыт работы с датами в Microsoft
Запросы и команды на языке SQL
Access и привыкли использовать для этого символ #, придется учесть это новшество и заменить символы # одиночными кавычками. ) 2 3 5 6
IcustanertD lOnterPat» 1 '/4/2001 I ' • 1/9/2001 2 1/14/2001 2/18/2001 i4 J3/21/2001 ,4 '4/4/2001
'•""le
I
' „Ш
РИС. 2.4. Результаты выполнения запроса для таблицы tblOrder с использованиям предложения SELECT и оператора BETWEEN
Границы оператора BETWEEN являются включающими; это значит, что если вы запрашиваете информацию обо всех заказах, оформленных за период с 4 января по 5 июня 2001 года, то в результирующий набор включаются заказы, которые были оформлены как 4 января, так и 5 июня.
Оператор LIKE и символы шаблона С помощью оператора LIKE отбираются записи, соответствующие заданному шаблону. Этот шаблон обычно состоит из так называемых подстановочных символов (wildcard characters) * или ?, с которыми вы, возможно, уже знакомы по работе с файловыми системами MS DOS или Windows. Символ процента (%) означает частичное соответствие. Например, чтобы отобрать в таблице tblCustomer все записи, в которых фамилия начинается с буквы J, можно воспользоваться приведенным ниже запросом. SELECT ID, FirstName, LastName, Address, City, State FROM tblCustomer
WHERE
[LastName] LIKE ' J % '
В результате выполнения этого запроса будут извлечены записи для тех клиентов, фамилии которых начинаются с буквы J. При создании шаблонов можно также использовать символ подчеркивания. Он занимает место только одного символа в шаблоне. Например, чтобы отобрать всех клиентов, у которых почтовый индекс состоит из пяти цифр и начинается с числа 80, воспользуйтесь следующей командой SQL: SELECT ID, FirstName, LastName, Address, PostalCode FROM tblCustomer WHERE PostalCode LIKE '80 ' В результате выполнения этого запроса будут извлечены записи для тех клиентов, почтовый индекс которых начинается с числа 80. Оператор LIKE можно использовать также для отбора записей на основе вхождения в диапазон определенных алфавитных или числовых значений. Например, чтобы возвратить список клиентов, фамилии которых начинаются с букв в диапазоне от А до М, используйте приведенную ниже команду SQL. SELECT ID, FirstName, LastName FROM tblCustomer
WHERE LastName LIKE ' [ A - M ] % '
В результате выполнения этого запроса будут извлечены пять записей для тех клиентов, фамилии которых начинаются с букв в диапазоне от А до М.
Глава 2
Действие символов подстановки в Microsoft Access отличается от действия этих же j символов в стандартном SQL. В Microsoft Access символ звездочки используется j вместо символа процента для подбора любого числа произвольных символов, а сим- - j вол знака вопроса — вместо символа подчеркивания для подбора любого одиночно- I го символа. В стандартном SQL символ подчеркивания используется для подбора i любого числа произвольных символов, а символ процента — для подбора любого \ одиночного символа.
Оператор IN Этот оператор используется для отбора записей, которые соответствуют элементам из заданного списка значений. Например, чтобы отобрать всех клиентов в штатах Колорадо (СО) или Висконсин (WI), воспользуйтесь приведенной ниже инструкцией SQL. SELECT FirstName, LastName, State FROM tblCustoraer WHERE State IN ( ' C O ' , ' W I ' ) В результате выполнения этого запроса будут извлечены три записи для тех клиентов, которые живут в штатах Колорадо или Висконсин. Как видите, с помощью оператора IN можно получить те же результаты, что и с помощью оператора OR. Некоторые разработчики предпочитают применять оператор IN при использовании нескольких критериев, поскольку в таком случае команда SQL выглядит более аккуратно.
Сортировка результатов с помощью предложения ORDER BY Предложение ORDER BY формирует для процессора баз данных команду на сортировку отобранных записей. Можно сортировать по любому полю или нескольким полям, причем как в возрастающей, так и в убывающей последовательности. Для того чтобы задать порядок сортировки, добавьте в конец обычного запроса SELECT предложение ORDER BY, а за ним укажите поле или поля, по которым нужно выполнить сортировку. Например, чтобы отобрать список клиентов, отсортированный по фамилии, воспользуйтесь приведенной ниже инструкцией SQL. SELECT ID, FirstName, LastName FROM tblCustomer ORDER BY LastName В результате выполнения этого запроса из таблицы tblCustomer будут извлечены все записи, упорядоченные по фамилиям клиентов.
Сортировка в убывающей последовательности Для сортировки в убывающей последовательности задайте ключевое слово DESC после имени поля, по которому проводится сортировка. Например, если нужно ото-
Запросы и команды на языке SQL
брать из таблицы tbl Order записи так, чтобы сначала располагались самые последние заказы, воспользуйтесь следующей командой SQL: SELECT *
FROM tblOrder ORDER BY OrderDate DESC
В результате выполнения этого запроса из таблицы tblOrder будут извлечены все записи, причем сначала будут располагаться самые последние заказы.
Сортировка по нескольким полям Для того чтобы отсортировать записи по нескольким полям, после предложения ORDER BY перечислите поля друг за другом через запятую. Например, чтобы отсортировать записи в таблице tblCustomer по фамилии, а затем по имени, воспользуйтесь приведенной ниже командой SQL. SELECT FirstName, LastName, City, State FROM tblCustomer ORDER BY LastName, FirstName
В результате выполнения этого запроса из таблицы tblCustomer будут извлечены все записи, отсортированные по фамилиям, а затем по именам (например, за клиентом Betty Klein будет располагаться клиент Daisy Klein).
Отображение первых или последних записей диапазона с помощью предложения ТОР Ключевое слово ТОР используется для отображения некоторого количества начальных или конечных записей из большого результирующего набора. Для ограничения числа записей в результирующем наборе ключевое слово ТОР в запросах сочетается с предложением, указывающим порядок сортировки. Причем ключевое слово ТОР можно комбинировать как с числом, означающим количество записей, так и с числом, означающим процентное содержание отображаемых записей. Например, необходимо отобрать три наиболее крупных заказа из числа последних заказов в таблице tblOrder. Для этого воспользуйтесь приведенной ниже инструкцией SQL. SELECT ID, OrderDate, CustomerlD FROM tblOrder ORDER BY OrderDate DESC
Обратите внимание, что ключевое слово DESC сортирует результирующий набор по убыванию. В результате выполнения этого запроса из таблицы tblOrder будут извлечены сведения о заказах каждого клиента, причем сначала будут располагаться самые последние заказы. Все просто прекрасно, за исключением того, что в базе данных, которая хранит информацию обо всех когда-либо выполненных заказах, придется просмотреть тысячи записей, в то время как вас интересуют только три наиболее
Глава 2
крупных заказа. Поэтому вместо предыдущей команды попробуйте выполнить приведенную ниже инструкцию SQL. SELECT TOP 3 *
FROM tblOrder ORDER BY OrderAmount DESC В результате выполнения этого запроса из таблицы tblOrder будут извлечены три записи для наиболее крупных заказов. Почему же запрос вернул четыре записи вместо запрошенных трех? Такой запрос (ТОР 3) вовсе не гарантирует, что будут возвращены только три записи. Возможно, что результирующий набор будет содержать одну или две записи (или даже ни одной), если в таблице содержится только такое количество записей. А если на последнее место в результирующем наборе претендуют две и более записи, то вполне возможно, что будут возвращены четыре или даже большее количество записей. В синтаксисе SQL нет понятия BOTTOM N, но зато есть возможность возвратить заданное количество последних записей в таблице. Для того чтобы создать такой запрос, достаточно отсортировать записи в возрастающей последовательности (т.е. от самого малого значения к самому большому), как показано ниже. SELECT TOP 3 * FROM tblOrder ORDER BY OrderDate
Этот запрос показывает три самых "древних" заказа в базе данных. Сортировка данных в порядке возрастания в SQL принимается по умолчанию. Поэтому нет необходимости использовать ключевое слово АЗС для задания порядка сортировки по возрастанию.
Создание запросов TOP PERCENT Можно писать запросы, возвращающие записи, количество которых определяется заданным процентом от общего количества записей в таблице. Например, если у вас есть таблица с 1 000 записей и необходимо возвратить один процент первых записей, то, как правило, будет отображено 10 записей. (Возможно, будет отображено более 10 записей, если несколько записей имеют одинаковое значение. Такой же случай рассматривался и для запроса ТОР N.) Для возврата первых записей в результирующий набор, количество которых задано процентным отношением к общему количеству записей в таблице, используется предложение TOP N PERCENT. Например, чтобы отобрать первые 20% от неоплаченных заказов в таблице tblOrder, воспользуйтесь приведенной ниже командой SQL. SELECT TOP 20 PERCENT *
FROM tblOrder ORDER BY OrderDate DESC В результате выполнения этого запроса из таблицы tblOrder будут извлечены две записи для самых последних заказов, которые составляют 20% от 10 строк таблицы tblOrder.
Запросы и команды на языке SQL
Объединение связанных таблиц в запросе Для выборки связанной информации из нескольких таблиц используется объединение (join). Чтобы создать объединение в запросе, необходимо определить первичные (primary) и внешние (foreign) ключи в таблицах, участвующих в объединении (эти понятия обсуждаются в главе 1, "Основы построения баз данных"). Например, рассмотрим две связанные таблицы с показанными ниже структурами. tblCustomer
ID FirstName LastName Address City State PostalCode Phone
Fax Email tblOrder
ID CustomerlD OrderDate OrderAmount
Хотя в таблице tblOrder хранится информация о заказах, а в таблице tblCustomer— информация о клиентах, вполне вероятно, что вам потребуется, например, отобрать такую информацию о заказах клиентов, как показано ниже. FirstName
LastName
OrderDate
Jane
Winters
9/10/2001
Jane
Winters
8/16/2001
Thurston
Ryan
7/2/2001
Dave
Martin
6/5/2001
Daisy
Klein
4/4/2001
Глава 2
Такой результирующий набор нетрудно получить, используя объединение, несмотря на то что необходимые данные хранятся в разных таблицах. Можно надеяться на получение нужных данных, если сообщить процессору баз данных о том, что первичный ключ таблицы tblCustomer (ID) связан с внешним ключом (CustomerlD) таблицы tblOrder.
Обратите внимание, что в этом результате объединения один и тот же клиент ото- ; | бражен дважды, хотя его имя было введено в базу данных один раз. Это значит, что j I клиент имеет несколько заказов. Иными словами, при нескольких заказах одного и I i того же клиента вам не пришлось вводить в базу данных информацию об этом клиен- i те несколько раз. Вместе с тем в результате выполнения запроса иногда можно по| лучить избыточную информацию. Для исправления такой ситуации можно применять j несколько разных методов.
Выражение объединения в SQL В SQL Server объединение можно установить с помощью выражения эквивалентности между двумя полями, например: SELECT FirstName, LastName, OrderDate FROM tblOrder INNER JOIN tblCustomer ON tblOrder.CustomerlD = tblCustomer.ID Этот запрос SQL возвращает информацию обо всех клиентах, которые имеют заказы в таблице tblOrder. В результате выполнения запроса возвращаются три столбца данных: поля FirstName и LastName из таблицы tblCustomer, а также поле OrderDate из таблицы tblOrder. Обратите внимание, что в запросе с объединением таблиц при использовании полей, имеющих одинаковые имена, но принадлежащих разным таблицам, необходимо перед именем поля вставлять ссылку на соответствующую таблицу (например, tblOrder. ID вместо ID). В большинстве случаев при использовании конструктора представлений в среде Visual Studio .NET для создания запроса интегрированная среда разработки способна определить выполняемые действия и дополнить выражение недостающими частями. Как уже сообщалось ранее, в данной книге примеры инструкций SQL приводятся в наиболее кратком виде, а необязательные части применяются только в случае необходимости.
Использование конструктора представлений для создания объединений Поскольку создание объединений может составлять самую сложную часть запросов, особенно когда задействовано более двух таблиц, неплохо было бы при создании таких запросов иметь некоторое подспорье. К счастью, в Visual Basic предусмотрен конструктор представлений (View Designer), благодаря которому создание запроса с объединением нескольких таблиц значительно упрощается. При использовании конструктора представлений нет необходимости запоминать сложный синтаксис
Запросы и команды на языке SQL
объединения в SQL. Вместо этого можно создать объединение графическим путем, выполнив приведенные ниже действия. 1. В окне Server Explorer создайте новое представление для базы данных Novelty. 2. После этого появится диалоговое окно Add Table (Создать таблицу), в котором следует указать таблицы tblCustomer и tblOrder, а затем щелкнуть на кнопке Close. Схема представления в окне конструктора представлений показана на рис. 2.5. I]* САП Columns) ZlID i rstName ULastName ZlCompany IjAddress DCi ty Gstate IJPostalCode HJPhone ZIFax ZlEmai 1
DID
3CustomerID QOrderDate
РИС. 2.5. Создание объединения двух таблиц в окне конструктора представлений Обратите внимание на то, что конструктор представлений автоматически создает объединение между двумя таблицами на основе известного ключевого поля ID в таблице tblCustomer и явно заданного ранее отношения с полем CustomerlD в таблице tblOrder. После выполнения запроса на основе объединения двух таблиц в окне конструктора представлений будут отображены извлеченные данные, как показано на рис. 2.6.
Использование внешних объединений Обычное (внутреннее) объединение (inner join) возвращает записи из двух таблиц, если значение первичного ключа первой таблицы соответствует значению внешнего ключа второй таблицы, связанной с первой. Предположим, необходимо получить все записи из одной таблицы, участвующей в объединении, вне зависимости от того, существуют ли связанные записи в другой таблице. В этом случае необходимо использовать внешнее объединение (outerjoin). Например, для извлечения списка клиентов и заказов, в который включены также клиенты, не имеющие неоплаченных заказов, можно использовать приведенный ниже запрос. SELECT FirstName, LastName, OrderDate FROM tblCustomer LEFT OUTER JOIN tblOrder ON tblCustomer.ID = tblOrder.CustomerlD
Обратите внимание, что в предложении LEFT JOIN используется синтаксис имА_таблицы. имя_поля. Более длинное имя позволяет избежать неоднозначности при использовании полей с одинаковыми именами, поскольку поле ID существует как в
Глава 2
tblCustomer, так и в tblOrder. Фактически предложение LEFT OUTER JOIN означает, что будут отображены все данные таблицы tblCustomer, которая находится з левой стороне выраженияtblCustomer.ID = tblOrder.CustomerlD. P* (All Columns J DID
rstName SLastName DCompany I ..... 1 Address Dei ty instate QPostalCode DPhone
* (All Columns)
DID
IlCustomerlD SlOrderDate
DEmai 1
Column FT rstName LastName OrderDate
tblCustomer | tlTl Customer
[tbl Order
[output .[sort type
у у"
[sort Order [criteria
v
SELECT dbo.tblCustomer.FirstName, d b о. t Ы С u stomer. L a s tName, dbo.tblOrder.OrderDate FROM dbo.tblCustomer INNER JOIN dbo.tblOrder ON dbo.tblCustomer.ID = dbo.tblOrder.CustomerlD
John John Jin Dai sy Daisy Dai sy Dave Thurston Jane Jane
Smi th 1/4/2001 il/9/2001 : Smith !iyi4/200l1 iAzali a [2 /18/2 001 i :kYein ^3/21/2001 [Klein : JKlein 4/4/2001 1 Marti n !6/5/200l ! Ryan ;77272001 : ;Winters 18/16/2001^ iwi nters iVlO/2001:
!
РИС. 2.6. Выполнение запроса на основе объединения двух таблиц в окне конструктора представлений Этот запрос возвращает приведенный ниже набор записей. FirstName
LastName
OrderDate
John
Smith
1/4/2001
John
Smith
1/9/2001
i'U
Azalia
1/14/2001
Зап росы и команды на языке SQL
FirstName
LastName
OrderDate
Brad
Jones
Daisy
Klein
2/18/2001
Daisy
Klein
3/21/2001
Daisy
Klein
4/4/2001
Dave
Martin
6/5/2001
Betty
Klein
Thurston
Ryan
7/2/2001
Jane
Winters
8/16/2001
Jane
Winters
9/10/2001
01
В этот результирующий набор включены все клиенты базы данных, независимо от того, имеют ли они заказы или нет. Для клиентов, не имеющих заказов, в поле OrderDate появится , что означает отсутствие данных. Правое внешнее объединение (right join) аналогично левому внешнему объединению (left join), за исключением того, что оно возвращает все записи из второй таблицы, участвующей в объединении (имеется в виду таблица с правой стороны), независимо от того, есть ли соответствующие им записи в первой таблице (расположенной с левой стороны). (Левое и правое объединения являются разновидностями внешнего объединения и в определенных обстоятельствах могут возвращать идентичные результаты.)
Выполнение вычислений в запросах В строках запроса допускается выполнение вычислений. Для этого нужно просто заменить имя поля в предложении SELECT именем арифметического выражения. Допустим, вам нужно создать запрос для вычисления налога с продаж для складских запасов (сведения о которых хранятся в таблице tblltem). В приведенном ниже запросе SQL вычисляется налог с продаж с учетной ставкой 7,5% для каждого товара. SELECT ID, Item, Price, Price * 0.075 AS SalesTax FROM tblltem После выполнения этого запроса будут получен показанный ниже результат. ID
Name
Price
SalesTax
1
Rubber Chicken
5.99
0.44925
2
Hand Buzzer
1.39
0.10425
3
Stink Bomb
1.29
0.09675
4
Disappearing Penny Magic Trick
3.99
0.29925
5
Invisible Ink
2.29
0.17175
6
Loaded Dice
3.49
0.26175
5.99
0.44925
7
Whoopee Cushion
Глава 2
Поскольку в этих вычислениях фигурируют деньги, конечный результат нужно округлить до двух десятичных знаков. К счастью, в SQL Server для этого предусмотрена специальная функция ROUND, которая позволяет очень легко выполнить это. Обычно ее используют с указанием двух параметров: собственно десятичного числа и точности, выраженной в виДе количества знаков после запятой. Вот как выглядит запрос с функцией ROUND: SELECT Name, Retail Price, ROUND (Retail Price AS PriceWithTax FROM tbllnventory
+ Retail Price * 0.075, 2)
Результат выполнения этого запроса приведен ниже. Name
Retail Price
PriceWithTax
Rubber Chicken
5.99
6.44
Hand Buzzer
1.39
1.49
Stink Bomb
1.29
1.39
Disappearing Penny Magic Trick
3.99
4.29
Invisible Ink
2.29
2.46
Loaded Dice
3.49
3.75
Whoopee Cushion
5.99
6.44
Определение псевдонимов с использованием предложения AS Из предыдущего примера ясно, что существует возможность определения псевдонимов (alias), т.е. переименования полей в запросе. Это может быть вызвано следующими причинами: •
в основной таблице имена полей могут быть громоздкими, а в результирующем наборе должны быть понятными и простыми;
•
запрос создает столбец, который заполняется в результате некоторых вычислений или операций подведения итогов, а новому столбцу обязательно нужно задать имя.
Независимо от причины, это легко сделать в запросе SQL с помощью предложения AS. Например, вам нужно выполнить ряд сложных вычислений для определения суммарной стоимости отгруженных товаров ExtendedPrice. Для этого напишите следующий код SQL: SELECT TOP 5 ItemID, Quantity, Price, tbllnventory.ReatilPrice * tblOrderTime.Quantity AS ExtendedPrice FROM tblOrderTime INNER JOIN tbllnventory ON tblOrderTime.ItemID = tblltem.ID Этот запрос возвращает приведенный ниже результирующий набор.
Запросы и команды на языке bQL ,7"
ItemID
Quantity
RetailPrice
ExtendedPrice
1
1
5.99
5.99
2
2
1.39
2.78
5
3
2.29
6.87
4
2
3.99
7.98
7
1
5.99
5.99
О7
83
Обратите внимание, что данные в поле ExtendedPrice не хранятся в базе данных, они вычислены "на лету".
Запросы, которые группируют данные и подводят итоги Часто требуется создавать запросы, подобные следующему: "Сколько заказов поступило вчера?" При этом вас не интересует, кто оформил заказ, вы только хотите знать количество вчерашних заказов. Это можно сделать, используя запросы, группирующие итоговые функции. Запросы с группировкой подводят итоги по одному или нескольким полям. Например, если вам интересно увидеть число заказов для каждого клиента, то нужно создать приведенный ниже запрос для таблицы tblOrder с группировкой данных по полю CustomerlD. SELECT CustomerlD, COUNT(CustomerlD) AS TotalOrders FROM tblOrder GROUP BY CustomerlD Результат выполнения такого запроса приведен ниже. CustomerlD
TotalOrders
1
2
2
1
4
3
5
1
7
1
8
2
Обратите внимание на использование предложения AS в этом выражении SQL. Оно предназначено для присвоения имени столбцу, содержащему результат итоговой функции, поскольку этот результат вычисляется, а не хранится в базе данных. Для отображения имен клиентов вместо их идентификаторов нужно просто объединить с результатами запроса данные из таблицы tblCustomer. SELECT tblOrder.CustomerlD, FirstName, LastName COUNT(dbo.tblOrder.CustomerlD) AS TotalOrders
Глава 2 FROM tblOrder INNER JOIN tblCustomer ON tblOrder.CustomerID = tblCustomer.ID GROUP BY FirstName, LastName, CustomerlD После выполнения такого запроса будет получен приведенный ниже результат. CustomerlD
FirstName
LastName
TotalOrders
1
John
Smith
2
1
4
Jill Daisy
Azalia Klein
3
5
Dave
Martin
1
7
Thurston
Ryan
1
8
Jane
Winters
2
2
В этом случае предложение GROUP BY содержит поле CustomerlD вместе с объединенными полями FirstName и LastName из таблицы tblCustomer. При использовании предложения GROUP BY в него необходимо включить все поля, по которым группируются извлекаемые записи. В данном случае идентификатор клиента и его имя участвуют в группировании данных и потому присутствуют в предложении GROUP BY. (К счастью, если вы забудете выполнить эту операцию, среда Visual Studio .NET автоматически предложит вам сделать это.)
Применение предложения HAVING для группирования данных в запросах Как уже отмечалось выше, критерий запроса служит для ограничения количества извлекаемых записей. В обычных запросах для включения критериев используется предложение WHERE, в запросах с группированием— предложение HAVING. Эти предложения применяются совершенно одинаково, за исключением того, что HAVING относится к агрегированным строкам (т.е. к результату группирования), а. WHERE — к отдельным строкам. Это довольно незначительное отличие, потому что в 9 случаях из 10 они дают совершенно одинаковый результат. Например для создания отчета о продажах клиента Jane с группированием данных можно использовать приведенный ниже запрос. SELECT tblOrder.CustomerlD, FirstName, LastName, COUNT(dbo.tblOrder.CustomerlD) AS TotalOrders FROM tblOrder INNER JOIN tblCustomer ON tblOrder.CustomerlD = tblCustomer.ID GROUP BY FirstName, LastName, CustomerlD HAVING FirstName = 'Jane' Этот запрос возвращает одну запись для клиента Jane Winters с указанием двух сделанных ею заказов. Допустим, теперь нужно получить список активных покупателей, т.е. клиентов, сделавших более одного заказа. Поскольку агрегированное количество заказов хранится в вычисленном поле TotalOrders, можно предположить, что для определения таких клиентов допустимо использовать выражение HAVING TotalOrders > 1. К сожалению, это выражение некорректно, так как TotalOrders — это не поле базы
Запросы и команды на языке SQL
данных, а вычисленное поле. Вместо этого следует включить данное вычисление в предложение HAVING показанного ниже запроса. SELECT tblOrder.CustomerlD, FirstName, LastName, COUNT(dbo.tblOrder.CustomerlD) AS TotalOrders FROM tblOrder INNER JOIN tblCustomer ON tblOrder.CustomerlD = tblCustomer.ID GROUP BY FirstName, LastName, CustomerlD HAVING (COUNT(tblOrder.CustomerlD) > 1) После выполнения этого запроса будут получены три строки, каждая из которых содержит номер, имя, фамилию и количество заказов для каждого клиента, который сделал более одного заказа. CustomerlD
FirstName
LastName
TotalOrders
1
John
Smith
2
4
Daisy
Klein
3
8
Jane
Winters
2
Функция SUM Ваши возможности в подведении итогов не ограничены простым подсчетом записей. Используя функцию SUM, можно генерировать итоговые результаты для всех возвращаемых записей по любым числовым полям. Например, для создания запроса, который генерирует итоги по количеству заказанных товаров каждым клиентом, необходимо написать следующую команду SQL: SELECT OrderlD, SUM(Quantity) AS Totalltems FROM tblOrderltem GROUP BY OrderlD Этот запрос возвращает приведенный ниже результирующий набор. OrderlD
Totalltems
1
6
2
2
3
1
4
23
5
4
6
13
7
12
8
3
9
4
10
4
Как и в предыдущих примерах группирования, если вы захотите извлечь дополнительную связанную информацию (например, имя и фамилию клиента), следует
Глава 2
использовать объединение с другой таблицей. Помните, что для агрегирования данных потребуется сгруппировать данные по крайней мере по одному полю.
Перечень итоговых функций В табл. 2.2 перечислены все итоговые функции, доступные в SQL.
Таблица 2.2. Итоговые функции SQL Функция
Результат
AVG
Среднее значение от всех значений в столбце
COUNT
Общее количество отобранных записей
МАХ
Максимальное (наибольшее) значение поля
MIN
Минимальное (наименьшее) значение поля
STDEV
Среднеквадратическое отклонение
SUM
Общая сумма всех значений в поле
VAR
Дисперсия
Синтаксис этих функций, по сути, соответствует синтаксису функции COUNT, которая рассматривалась в предыдущем разделе. Например, для ежедневного вычисления среднего количества товаров в каждом заказе воспользуйтесь приведенным ниже запросом SQL. SELECT AVG(tblOrderItem.Quantity) AS AverageLineltemQuantity FROM tblOrder INNER JOIN tblOrderltem ON tblOrder.ID = tblOrderItem.OrderlD Этот запрос возвращает значение 2, т.е. количество товаров в заказах всех клиентов. Вычисления и итоговые функции можно комбинировать разными способами. Например, чтобы получить список со стоимостью всех товаров в каждом заказе, нужно определить стоимость товара (эти сведения хранятся в таблице tbl Inventory) в каждом заказе и умножить ее на количество этих товаров в заказе (эти сведения хранятся в таблице tblOrderltem), азатем сложить полученные произведения в каждом заказе. SELECT t b l O r d e r l t e m . O r d e r l D , SUM(Quantity * Price) AS OrderTotal FROM tblInventory INNER JOIN tblOrderltem ON t b l l t e m . I D = tblOrderltem.OrderlD GROUP BY .OrderlD
Этот запрос возвращает приведенный ниже результирующий набор. OrderlD
OrderTotal
1
15.64
2
7.98
3
5.99
4
99.17
Запросы и команды на языке SQL
OrderlD
OrderTotal
5
13.96
6
49.07
7
55.88
8
13.97
9
9.16
10
14.76
Запросы на объединение Запрос на объединение (union query) выполняет объединение содержимого двух таблиц, имеющих одинаковые структуры полей. Это оказывается полезным, когда нужно отобразить в одном результирующем наборе потенциально не связанные записи из нескольких источников. Далее в главе приводятся примеры сохранения старых заказов в архивной таблице с именем tblOrderArchive. И если вы воспользуетесь предложенной системой архивирования, то записи физически будут размещены в двух отдельных таблицах. Это может повысить эффективность работы: запрос выполняется быстрее на маленькой таблице, чем на большой. Но, возможно, в некоторых случаях понадобится просмотреть все текущие и заархивированные записи в одном общем результирующем наборе. С такой задачей прекрасно справится запрос на объединение. Предположим, что как раз возникла необходимость в просмотре в одном результирующем наборе старых записей из таблицы tblOrderArchive и новых записей из tblOrder. Такой запрос приведен ниже. SELECT
*
FROM tblOrder UNION SELECT *
FROM tblOrderArchive
После выполнения этого запроса старые и новые заказы объединятся в одном результирующем наборе, причем результат будет выглядеть подобно исходной таблице до архивирования. По умолчанию запрос на объединение не возвращает записи-дубликаты (хотя было бы неплохо, чтобы ваша система архивирования записей не удаляла их после копирования в таблицу архива). Отображение записей-дубликатов может оказаться весьма полезным, если система архивирования старых записей не удаляет записи после копирования в архивную таблицу и вам нужно просмотреть и сравнить некоторые старые и новые записи. Однако, добавив ключевое слово ALL, можно заставить запрос на объединение отображать дублирующие записи, как показано ниже. SELECT *
FROM tblOrder
UNION ALL SELECT *
FROM
tblOrderArchive
Глава 2
Подзапросы Подзапрос (subquery) — это запрос, результат которого служит критерием для другого запроса. Подзапросы занимают место обычного выражения WHERE. Поскольку результат, сгенерированный подзапросом, используется вместо выражения, подзапрос может возвращать только одиночное значение (в противоположность обычному запросу, который возвращает несколько значений, представленных в виде строк и столбцов). Единственное синтаксическое различие между подзапросом и выражением любого другого типа, размещенным в предложении WHERE, состоит в том, что подзапрос должен быть заключен в круглые скобки. Например, нужно создать запрос, который отображает заказы с самыми дорогими товарами. Дорогим считается такой товар, стоимость которого превышает среднюю стоимость товаров в таблице tblltem. Поскольку среднюю стоимость товара легко определить (выполнив итоговую функцию AVG по полю UnitPrice в таблице tblltem), это значение можно использовать как подзапрос в более крупном запросе. Такой запрос SQL приведен ниже. SELECT Name, UnitPrice FROM tblltem WHERE (UnitPrice > (SELECT AVG(UnitPrice) FROM tblltem) В этом случае оказывается, что запрос и подзапрос обращаются к одной и той же таблице, но это не принципиально. Подзапросы могут делать запросы к любой таблице в базе данных, главное — чтобы они возвращали одиночное значение. Приведенная выше инструкция SQL возвращает следующий результирующий набор: Name
UnitPrice
Rubber Chicken
5.99
Disappearing Penny Magic Trick
3.99
Loaded Dice
3.49
Whoopee Cushion
5.99
Манипулирование данными с помощью SQL Команда манипулирования данными (data manipulation command) — это команда SQL, которая изменяет записи. Такие команды создаются на языке манипулирования данными DML, который является подмножеством языка SQL. Эти команды не возвращают записи, а только изменяют их в базе данных. DML-команды SQL обычно применяются для изменения большого объема данных на основе заданного критерия. Например, для повышения на 10% цены всех товаров следует использовать запрос на обновление, который автоматически выполнит такие изменения для всех товаров. В среде Visual Studio .NET предусмотрен очень мощный интерфейс для выполнения DML-команд. Действительно, инструменты среды Visual Studio .NET могут пре-
Запросы и команды на языке SQL
доставить полезную информацию (например, правильную строку подключения для соединения с базой данных) или генерировать в окне конструктора основные DMLкоманды при извлечении данных из таблицы или изменении типа запроса.
-
—
:
—
;
|
Примеры в этом разделе демонстрируют способы изменения данных в базе данных i | Novelty. Если после многочисленных попыток изменить данные вы хотите вернуть ! базу данных Novelty в ее прежнее состояние, то ее можно переустановить, запуская i описанный во введении к этой книге сценарий. На низком уровне (т.е. не на уровне графического интерфейса пользователя) DML-команды SQL можно использовать с помощью следующих двух инструментов: •
•
Microsoft SQL Server Query Analyzer (или просто Query Analyzer) — инструмент с графическим интерфейсом пользователя для создания запросов и команд для SQL Server; osql — используемый в режиме командной строки процессор запросов.
Вы можете использовать любой из этих инструментов, а в данной главе применяется Query Analyzer, который обладает более широкими возможностями и более удобен в употреблении, чем процессор запросов osql. В настоящей главе основное внимание сосредоточено на фактически выполняемых командах, а не на методах использования графического интерфейса Query Analyzer. Инструмент Query Analyzer находится в группе программ Microsoft SQL Server. (В главе 7, "ADO.NET: дополнительные компоненты", более подробно рассматриваются способы применения DML-команд в среде Visual Studio .NET.)
Запросы на обновление Запрос на обновление может изменить сразу целую группу записей. Этот запрос состоит из трех частей: •
предложение UPDATE, которое указывает на обновляемую таблицу;
•
предложение SET, задающее данные для обновления;
• необязательный критерий WHERE, ограничивающий число записей, на которые воздействует запрос на обновление. Например, чтобы увеличить цену на все товары, воспользуйтесь запросом на обновление, код которого приведен ниже. UPDATE tblltem SET Price = Price * 1.1 SELECT * FROM tblltem Команда SELECT, которая располагается вслед за предложением UPDATE, не обязательна и предназначена для просмотра результатов обновления. Ниже приведены значения полей после выполнения данного запроса на обновление.
Глава 2
0Л
и
ID
Name
Description
UnitPrice
Price
Rubber Chicken
A classic laugh getter
2.0300
6.5890
Hand Buzzer
Shock your friends
.8600
1.5290
!
Stink Bomb
Perfect for ending boring meetings
.3400
1.4190
4
Invisible Ink
Write down your most intimate thoughts
1.4500
2.5190
5
Loaded Dice
Not for gambling purposes
1.4600
3.8390
6
Whoopee Cushion
The ultimate family gag
2.0300
6.5890
1
Для ограничения числа записей, подвергаемых воздействию запроса на обновление, достаточно добавить в запрос SQL предложение WHERE. Например, чтобы применить повышение цен только к дорогим товарам, стоимость которых больше $100, откорректируйте запрос так, как показано ниже. UPDATE tblltem SET Price = Price * 1.1 WHERE Price > 100 Эта команда увеличивает на 10% цену на товары, текущая цена которых больше $100.
Запросы на удаление С помощью запроса на удаление (delete query) можно одним махом удалить одну или несколько записей. Например, чтобы удалить все заказы, которые были оформлены до (но не во время) последнего празднования Дня всех святых, воспользуйтесь запросом SQL, код которого приведен ниже. DELETE *
FROM tblOrder WHERE OrderDate < '10/31/2002'
Запрос на добавление записей Запрос на добавление (append query) используется в двух случаях: • •
при добавлении одиночной записи в таблицу; при копировании одной или нескольких записей из одной таблицы в другую.
Для создания запроса на добавление используйте предложение SQL INSERT. Точный синтаксис запроса зависит от того, добавляете ли вы одну запись или копируете несколько. Например, для добавления одной новой записи в tblOrder можно использовать приведенный ниже запрос. INSERT INTO tblOrder(CustomerlD, OrderDate) VALUES (119, '6/16/2001') При выполнении этого запроса в таблице tblOrder создается новый заказ для клиента с идентификационным номером 119 и датой 16 июня 2001 года.
Запросы и команды на языке SQL
! В этом запросе на добавление для поля ID таблицы tblOrder не предлагается никакого значения, так как это поле идентификации. Попытка пользователя присвоить значение этому полю приведет к возникновению ошибки, поскольку его может сгеj нерировать только сам процессор баз данных. Для создания разновидности запроса на добавление, который копирует записи из одной таблицы в другую, используйте предложение INSERT вместе с предложением SELECT. Предположим, вместо удаления старых заказов вы архивируете их, периодически копируя в архивную таблицу tblOrderArchive, которая имеет ту же структуру, что и tblOrder. Для выполнения этой работы необходимо сначала создать таблицу tblOrderArchive со структурой, аналогичной tblOrder. CREATE TABLE tblOrderArchive ( ID [int] NOT NULL, CustomerlD [int] NULL, OrderDate [datetime] NULL
i Как уже сообщалось выше, команды SQL для создания и управления структурой базы ; данных называются командами манипулирования данными или DML-командами. БоI лее подробно они рассматриваются далее в главе.
Ниже приведена инструкция SQL для копирования старых записей из tblOrder в tblOrderArchive. INSERT INTO tblOrderArchive SELECT * FROM tblOrder WHERE OrderDate < '6/1/2001' При выполнении этой инструкции SQL в таблицу tblOrderArchive копируются все записи, содержащие заказы, которые были оформлены до 1 июня 2001 года.
Запросы на основе команды SELECT INTO Запрос на основе команды SELECT INTO аналогичен запросу на добавление, за исключением того, что он создает новую таблицу и сразу же копирует в нее записи. В Microsoft Access он называется запросом на создание таблиц (make-table query). Так, в предыдущем примере все записи из таблицы tblOrder копировались в таблицу tblOrderArchive, исходя из предположения, что таблица tblOrderArchive уже существует. Вместо этого запроса для копирования тех же записей в новую таблицу с такой же структурой, как и у оригинала, воспользуйтесь приведенным ниже запросом SQL. SELECT * INTO tblOrderArchive FROM tblOrder
Этот запрос копирует все записи из tblOrder в новую таблицу с именем tblOrder- j Archive. Однако ecjjn такая таблица уже существует, эта команда не будет выполнена. Это отличается от результата выполнения данного запроса в Microsoft Access.
Глава 2
: Если его выполнить в окне конструктора запросов программы Access при условии, что таблица tblOrderArchive уже существует, то процессор баз данных удалит ис-1 ходную таблицу и заменит ее вновь созданной, которая будет заполнена содержи> мым скопированных записей. В SQL Server для удаления таблицы нужно использо- :
| вать DDL-команду DROP TABLE.
В запросе на основе команды SELECT INTO можно применить критерий отбора (с помощью предложения WHERE) точно так же, как это делалось в запросе на добавление (см. предыдущий раздел). Это дает возможность копировать подмножество записей из исходной таблицы в новую, которая формируется запросом на создание таблицы.
Использование языка определения данных Команды языка определения данных (Data Definition Language — DDL) представляют собой инструкции SQL, которые позволяют создавать элементы структуры базы данных, манипулировать ими и удалять. Используя DDL, можно создавать и удалять таблицы, а также изменять структуру этих таблиц. Команды DDL относятся к наиболее редко используемым инструкциям в SQL в основном потому, что существует множество прекрасных инструментов, которые позволяют легко справиться с задачами создания таблиц, полей и индексов. В среде Visual Studio .NET DDL-команды SQL используются незаметно для разработчика при создании схемы базы данных в окне Server Explorer, но в ней не предусмотрены инструменты для непосредственного выполнения команд SQL по отношению к базе данных. Для этого следует применять инструменты Query Analyzer и osql либо использовать DDL-команды непосредственно в коде. Но если вы работаете в среде клиент/сервер, то для создания структуры базы данных удобнее использовать DDL-команды. Подобно командам манипулирования данными, DDL-команды не возвращают результирующих наборов (поэтому их и называют не запросами, а командами).
Создание элементов базы данных с помощью предложения CREATE Новые элементы базы данных создаются с помощью предложения SQL CREATE. Чтобы создать таблицу, используйте команду CREATE TABLE, за которой введите поля и типы данных, предназначенные для добавления в таблицу. В качестве разделителей используйте запятые, а весь список заключите в круглые скобки. Например, для создания новой таблицы можно применять приведенную ниже инструкцию SQL. CREATE TABLE tblRegion (State char (2), Region varchar (50)) Тип данных char ( 2 ) означает, что процессор баз данных должен создать текстовое поле фиксированной длины для хранения максимум двух символов, а выражение varchar (50} указывает на создание поля с переменной длиной до 50 символов.
Запросы и команды на языке SQL
При выполнении этого запроса будет создана таблица со следующей структурой: tblRegian
State Region В разделе о типах данных главы 1, "Основы построения баз данных", перечислены допустимые типы данных полей, которые можно использовать при создании полей.
Добавление ограничений в таблицу В процессе создания таблицы можно добавить ограничения (constraints). Они аналогичны индексу, но используются для обозначения уникального, первичного или внешнего ключа. Ограничение создается с помощью предложения SQL CONSTRAINT, которое принимает два параметра: имя индекса и имя поля или полей, в индексации которых вы заинтересованы. Можно объявить индекс с помощью ключевого слова UNIQUE или PRIMARY, и тогда этот индекс будет означать, что поле может принимать только уникальные значения или что поле (поля) служит первичным ключом таблицы. НА ЗАМЕТКУ
Понятие именованных индексов может показаться несколько странным для тех, кто ; привык работать в Microsoft Access, поскольку Access скрывает имена индексов в ! своем пользовательском интерфейсе. Однако к имени индекса можно получить дос- I I туп программным путем. Например, усовершенствовать таблицу tblRegion, созданную в предыдущем примере, можно добавлением уникального индекса к полю State, поскольку оно используется в объединении. Ниже представлена команда SQL, создающая эту таблицу с использованием предложения CONSTRAINT. CREATE TABLE tblRegion (State char (2), Region varchar (50), CONSTRAINT Statelndex UNIQUE (State)) Этот запрос создает таблицу с уникальным индексом по полю State, причем этот индекс имеет имя Statelndex. Несмотря на то что в приведенном выше примере индексируется поле State, больше смысла было бы в том, чтобы сделать поле State первичным ключом таблицы. В этом случае вы получили бы гарантию того, что в поле State не было не только повторяющихся значений, но и значений NULL. Ниже приводится команда SQL, создающая таблицу tblRegionNew, в которой первичным ключом является поле State. CREATE TABLE tblRegionNew (State char (2), Region varchar (50), CONSTRAINT StatePrimary PRIMARY KEY (State))
Глава 2
Назначение внешнего ключа Для того чтобы назначить поле в качестве внешнего ключа, используйте ограничение FOREIGN KEY. Например, в структуре нашей базы данных существует отношение типа один-ко-многим между полем State таблицы tblRegion и соответствующим полем State таблицы tblCustomer. Команда SQL, используемая для создания таблицы tblCustomer, может выглядеть так, как показано ниже. CREATE TABLE tblCustomer (ID int identity(1,1), FirstName varchar (20), LastName varchar (30), Address varchar (100), City varchar (75) , State varchar (2) , CONSTRAINT IDPrimary PRIMARY KEY (ID), CONSTRAINT StateForeign FOREIGN KEY (State) REFERENCES tblRegionNew (State)) Обратите внимание, что внешний ключ в команде CREATE TABLE не создает индекс по этому внешнему ключу. Он только служит для создания отношения между двумя таблицами.
Создание индексов с помощью команды CREATE INDEX Помимо создания индексов в процессе формирования таблицы (с помощью предложения CONSTRAINT), можно также создавать индексы уже после того, как таблица сформирована (с помощью предложения CREATE INDEX). Это полезно в тех случаях, когда таблица уже существует (в то время как предложение CONSTRAINT применяется для формирования индексов только в момент создания таблицы). Для создания индекса в существующей таблице используйте приведенную ниже команду SQL. CREATE INDEX Statelndex ON tblCustomer (State)
Для того чтобы создать уникальный индекс, используйте ключевое слово UNIQUE, как показано ниже. CREATE UNIQUE INDEX Statelndex ON tblRegion (State)
Чтобы создать первичный индекс в существующей таблице, используйте приведенную ниже команду SQL. CREATE UNIQUE NONCLUSTERED INDEX Statelndex ON tblRegion ( State ) ON [PRIMARY]
Запросы и команды на языке SQL
Удаление таблиц и индексов с помощью предложения DROP Удалять элементы базы данных можно с помощью предложения DROP. Например, чтобы удалить таблицу, используйте приведенную ниже команду SQL. DROP TABLE tblRegion С помощью предложения DROP можно также удалить индекс в таблице, как показано ниже. DROP INDEX tblRegion.Statelndex Обратите внимание, что для удаления первичного ключа нужно знать имя этого ключа. У вас также есть возможность удалять отдельные поля таблиц. Для этого нужно использовать предложение DROP внутри предложения ALTER TABLE, как показано в следующем разделе. А для удаления базы данных применяется команда DROP DATABASE.
Модификация структуры таблицы с помощью предложения ALTER С помощью предложения ALTER можно изменить определения полей в таблице. Например, чтобы добавить поле CustomerType в tblCustomer, используйте приведенную ниже команду SQL. ALTER TABLE tblCustomer ADD CustomerType int Для того чтобы удалить поле из базы данных, используйте предложение DROP COLUMN вместе с предложением ALTER TABLE, как показано ниже. ALTER TABLE tblCustomer DROP COLUMN CustomerType Кроме того, с помощью предложения ALTER TABLE можно добавить в таблицу ограничения. Например, для создания отношения между таблицами tblCustomer и tblOrder с помощью предложения ALTER TABLE используйте приведенную ниже команду SQL. ALTER TABLE tblOrder ADD CONSTRAINT OrderForeignKey FOREIGN KEY (CustomerlD) REFERENCES tblCustomer (ID) Помните, что добавление ограничения не создает обычного индекса по полю, оно просто делает поле уникальным, назначает поле первичным ключом или создает отношение между двумя таблицами.
Глава 2
Резюме Эта глава посвящена технологии создания запросов, которые могут использоваться в приложениях доступа к базам данных, созданных в среде Visual Basic .NET. Здесь рассматривались запросы, которые возвращают необходимые записи, а также запросы, которые создают и модифицируют структуру баз данных. Большая часть материала этой главы приводится отнюдь не ради увеличения объема книги; начав программировать с использованием Visual Studio .NET и ADO.NET, вы почувствуете реальную пользу от прочитанного.
Вопросы и ответы Почему имена таблиц и полей иногда заключены в квадратные скобки? Квадратные скобки часто окружают имена объектов в среде Visual Studio .NET и административных инструментах SQL Server для исключения проблем при использовании имен с пробелами и другими зарезервированными символами и словами. Например в базе данных Northwind, которая инсталлируется вместе с SQL Server 2000, есть таблица с именем Order Details. Хотя в общем случае не рекомендуется включать пробелы в имена таблиц, ее все же можно использовать в SQL Server в виде [Order Details]. Однако инструменты с графическим интерфейсом, например в среде Visual Studio .NET, всегда добавляют квадратные скобки. Но в данной книге они не используются, чтобы исключить излишнюю работу по их вводу. Почему перед именем таблицы иногда используется приставка dbo? Что это такое? dbo— это вспомогательный квалификатор (или моникер), который используется в инструментах с графическим интерфейсом при работе с SQL Server. Он позволяет установить соединение заданного объекта базы данных с владельцем базы данных. Объекты базы данных могут иметь разных владельцев, a dbo представляет собой сокращенную форму записи следующего высказывания: "этот объект относится к владельцу используемой базы данных". Разные объекты одной базы данных вполне могут относиться к разным владельцам, хотя, конечно, следует признать, что такая ситуация встречается редко. В базах данных, в которых все объекты относятся к владельцу dbo, этот моникер можно опустить (однако инструменты с графическим интерфейсом все равно попытаются вставить его).
Знакомство с SQL Server 2000
В ЭТОЙ ГЛАВЕ... • Установка и запуск Microsoft SQL Server • Основы работы с SOL Server 20OO
• Резюме • Вопросы и ответы
Глава 3
В прошлом многие программисты начинали создание приложений баз данных, используя язык Visual Basic и базу данных Microsoft Access с ядром Jet. Как только база данных разрасталась до нескольких тысяч записей или к ее услугам обращались несколько пользователей, наступал "великий перелом". Конфликты при доступе к данным со стороны пользователей, уменьшение производительности и отсутствие удобных инструментов управления данными и сервером привели к тому, что разработчики стали искать способы решения этих проблем с помощью других архитектур баз данных. Одной из таких архитектур стала модель вычислений типа клиент/сервер (или модель распределенных вычислений). Суть архитектуры клиент/сервер заключается не только в предоставлении многопользовательского режима работы с базой данных, к тому же с такой задачей вполне может справляться Jet. В многопользовательской архитектуре несколько пользователей используют одни и те же данные в сети, т.е. один или несколько файлов базы данных находятся на сервере, к которому могут осуществлять доступ клиентские компьютеры. Несмотря на то что Microsoft Access также поддерживает многопользовательский режим работы, эту программу нельзя отнести к системам клиент/сервер, поскольку все необходимые операции выполняются на отдельном компьютере клиента. Например, для извлечения с помощью команды SQL одной записи из таблицы, включающей 50 тыс. записей, нужно перенести на компьютер клиента все строки (или по крайней мере их индексы) таблицы. При этом на стороне сервера не предусмотрено никакой "интеллектуальной" части для специализированной обработки данных, например для выполнения запроса и возвращения только запрошенных данных. В архитектуре клиент/сервер предусмотрена серверная часть (back end), т.е. специализированное программное обеспечение, которое способно извлекать и кэшировать данные, разрешать конфликты доступа к данным со стороны клиентов, а также обеспечивать безопасность. Например, СУБД SQL Server компании Microsoft получает запросы от клиентских компьютеров, выполняет их на серверном компьютере, а затем возвращает клиентскому компьютеру только запрошенные данные. Таким образом, для извлечения одной записи из таблицы, включающей 50 тыс. записей, серверу будет передана команда SELECT, серверное программное обеспечение выполнит эту команду и возвратит клиенту только искомую запись. Очевидно, что при этом сетевой трафик значительно сокращается, а общая производительность повышается еще и потому, что вычислительная мощность (т.е. быстрота работы процессора и объем оперативной памяти) компьютера-сервера гораздо выше, чем компьютера-клиента. Поэтому в такой архитектуре будут быстрее выполняться команды и извлекаться данные. Если вы работаете с Visual Basic .NET, то очевидно, что в качестве серверной части (или сервера баз данных) можно использовать Microsoft SQL Server, поставляемый вместе с Visual Basic .NET и Visual Studio .NET. Перечень разных версий Microsoft SQL Server, которые поставляются вместе с Visual Basic .NET и Visual Studio .NET, приводится далее в главе. СОВЕТ
Базы данных на основе ядра баз данных Jet (MDB) рекомендуется использовать только для простейших и ограниченных приложений. Благодаря появлению нового ядра SQL Server 2000 Desktop Engine (MSDE), предназначенного специально для баз данных небольшого размера, отпадает необходимость использования ядра Jet. Теперь размер базы данных SQL Server может расти, не требуя дополнительного кодирования или изменения ее структуры по мере роста системы.
Знакомство с SQL Server 2000
В этой главе внимание фокусируется на основах использования SQL Server 2000. Сначала предлагается введение, посвященное его установке, а затем излагаются базовые сведения об использовании SQL Server 2000, необходимые для понимания материала и примеров в остальной части книги. Излагаемого здесь материала вполне достаточно даже для тех, у кого вообще нет никакого опыта работы с SQL Server. Более того, даже разработчики с большим опытом работы с этой СУБД найдут здесь для себя много полезного. Рассмотрим следующую типичную ситуацию. Допустим, вы входите в команду разработчиков распределенного приложения с архитектурой клиент/сервер. Программисты, разрабатывающие серверную часть приложения, к моменту промежуточной сдачи проекта только на 95% подготовили функциональную версию сервера. Нужно приступать к работе, а серверная часть приложения не готова на все 100%. Более того, в вашем распоряжении может быть только 1-2 программиста с опытом создания серверной части. Поскольку программисты серверной части обладают довольно редким набором навыков, такая ситуация возникает довольно часто при создании приложений с архитектурой клиент/сервер. Таких специалистов труднее всего найти и удержать, а потому они работают с гораздо большим напряжением, чем остальные программисты. Кроме того, их гораздо сложнее заменить в случае неудачного выполнения работы. Более того, программисты клиентской части часто не могут завершить свою работу до тех пор, пока не будут исправлены ошибки в серверной части. Такую ситуацию называют трагедией одаренного программиста серверной части. Если вы принимали участие в проекте по созданию распределенного приложения с архитектурой клиент/сервер с несколькими разработчиками, то вам наверняка знакома эта ситуация. Одним из решений этой проблемы является создание прототипа клиентского приложения с использованием временного источника данных на основе Jet с последующей заменой его по окончании работы над серверной частью. Для этого обычно используется источник данных ODBC или OLEDB. Предлагаемый уровень абстракции на основе ODBC или OLEDB позволяет создавать и использовать в приложении прототип баз данных с переключением на реальную базу данных по окончании работа над проектом. Размещение одного или нескольких уровней абстракции между клиентом и сервером также делает работу программистов клиентской части независимой от деятельности программистов серверной части. Для программистов серверной части это означает, что они должны создать представления или хранимые процедуры, которые поставляют данные клиентам. В среде Visual Basic .NET эта цель достигается за счет создания компонентов. Более подробно способы создания представлений или хранимых процедур описываются в других разделах этой главы.
Установка и запуск Microsoft SQL Server Работа с сервером баз данных значительно отличается от совместного использования файла базы данных Microsoft Jet. Для успешной работы с SQL Server нужно познакомиться с новыми понятиями и дополнительными возможностями. Однако установка и использование SQL Server 2000 организована гораздо проще, чем в предыдущих версиях, особенно в версии 6.5 и более ранних.
Глава 3
Ниже перечисляются основные условия для установки и работы разных редакций сервера базы данных SQL Server 2000. •
SQL Server 2000 Standard Edition— это стандартная редакция, которая содержит основной сервер баз данных для рабочей группы или отдела.
•
SQL Server2000 Enterprise Edition— это корпоративная редакция, которая содержит все элементы стандартной редакции и предлагает повышенную производительность и другие компоненты для крупных организаций, Web-узлов и хранилищ данных.
• SQL Server 2000 Personal Edition— это персональная редакция, предназначенная для мобильных пользователей, которые часто отсоединены от своей сети, но нуждаются в SQL Server для локального хранения данных и запуска отдельных приложений на клиентском компьютере. В отличие от стандартной и корпоративной редакций, для которых требуется серверная версия операционной системы Windows NT или Windows 2000, персональная редакция может работать с Windows 2000 Professional, Windows NT 4.0 Workstation и Windows ME или Windows 98. Эта редакция ограничивает производительность сервера, если одновременно запущено более пяти пакетных заданий. • SQL Server 2000 Developer Edition — это редакция для разработчиков, включающая все элементы корпоративного издания, но с лицензией только для разработки и тестирования приложений SQL Server; она не может использоваться как рабочий сервер баз данных. •
SQL Server 2000 Desktop Engine (MSDE)— это настольное ядро, содержащее большинство элементов стандартной редакции. Оно может свободно распространяться как часть небольшого приложения или демонстрационных версий. Размер базы данных, поддерживаемой этим ядром, не превышает 2 Гбайт и, подобно персональной редакции, ее производительность заметно падает при выполнении одновременно более пяти пакетных заданий. Однако она не содержит графических инструментов разработки и управления.
С каждой редакцией Visual Basic .NET или Visual Studio .NET поставляется редакция MSDE сервера баз данных SQL Server 2000. Редакции Enterprise Developer Visual Studio .NET и Enterprise Architect Visual Studio .NET также включают редакцию для разработчиков Developer SQL Server 2000. При этом следует учитывать такие особенности: • MSDE не включает графических инструментов SQL Server, которые описываются в этой главе; поэтому с ней нельзя выполнять примеры из данной книги (тем не менее для доступа к MSDE в Visual Studio .NET предусмотрено несколько ограниченных графических инструментов); • редакция для разработчиков SQL Server 2000 Developer Edition может применяться только для разработки и тестирования приложений SQL Server, а для использования ее в качестве рабочего сервера баз данных нужно приобрести лицензии для серверной и клиентской части SQL Server 2000.
Знакомство с SQL Server 2000
• SQL Server 2000 Windows CE Edition— это редакция, используемая как хранилище данных на портативных устройствах под управлением операционной системы Windows СЕ и способная реплицировать данные из других изданий SQL Server 2000.
Требования для инсталляции SQL Server 2000 Для инсталляции SQL Server 2000 требуется компьютер с процессором Pentium (или совместимым с ним) с частотой не менее 166 МГц, пространство на жестком диске от 95 до 270 Мбайт (270 Мбайт для типичного варианта инсталляции и 44 Мбайт для Desktop Engine), дисковод для компакт-дисков, броузер Internet Explorer версии 5.0 или выше, а также совместимая операционная система (см. выше). Для оперативной памяти установлены следующие требования: • для стандартной редакции Standard Edition — минимум 64 Мбайт; • для корпоративной редакции Enterprise Edition — минимум 64 Мбайт (рекомендуется 128 Мбайт); • для персональной редакции Personal Edition — минимум 64 Мбайт для операционной системы Windows 2000 и 32 Мбайт для других операционных систем; • для редакции Developer Edition — минимум 64 Мбайт; •
для ядра Desktop Edition — минимум 64 Мбайт для операционной системы Windows 2000 и 32 Мбайт для других операционных систем.
Если вы уже пытались запускать SQL Server на компьютере с процессором Pentium (или совместимым с ним) с частотой 166 МГц и 64 Мбайт оперативной памяти, то убедились, что сервер баз данных работает очень медленно. Не удивляйтесь, ведь специалисты Microsoft предупредили вас, что это минимальные требования. SQL Server может работать на компьютере с такими скудными вычислительными ресурсами, но в реальной рабочей обстановке такая экономия может привести к печальным последствиям для вашего бизнеса. Если вы ограничены в средствах и можете модернизировать только какой-то один компонент аппаратного обеспечения, то в таком случае лучше инвестировать денежные средства в оперативную память, чем в более мощный процессор. Даже небольшое увеличение размера оперативной памяти может существенно повысить производительность системы.
Данная книга в основном посвящена вопросам создания решений для работы с базами данных на основе Visual Basic .NET. Поэтому здесь не рассматриваются другие многочисленные элементы SQL Server. Для получения более подробной информации на эту тему следует обратиться к официальной документации SQL Books Online, которая входит в состав комплекта программных продуктов SQL Server, или прочитать книгу М. Шпеника и О. Следжа Руководство администратора баз данных Microsoft* SQL Server™2000 (Издательский дом "Вильяме", 2001).
Глава 3
Установка SOL Server 2000 После выбора компьютера с необходимой конфигурацией можно перейти к установке. В целом процесс установки SQL Server 2000 очень прост, за исключением следующих особенностей: • •
он длится довольно долго; в процессе установки задается очень много на первый взгляд странных вопросов, которые не характерны для обычных приложений.
Время процесса установки сократить никак нельзя, а чтобы упростить поиск ответов на вопросы со стороны программы-инсталлятора SQL Server, далее приводятся небольшие пояснения. Вообще говоря, для установки SQL Server в небольших организациях достаточно использовать предлагаемые по умолчанию значения параметров в диалоговых окнах и экранах программы-мастера инсталляции. Поэтому приведенные далее комментарии относятся к наиболее сложным диалоговым окнам. В диалоговом окне Setup Type (Тип установки), которое показано на рис. 3.1, можно выбрать тип установки: Typical (Типичная), Minimum (Минимальная) и Custom (Специализированная), а также путь к каталогам, в которых будут установлены файлы SQL Server и данные. Перед установкой убедитесь в том, что на жестких дисках этих каталогов достаточно места для размещения данных и путь к ним указан среди параметров резервного копирования данных. Cick the type о* Setup you ре!м, then ctickNfSKt. '^ tSpcel
Instated wuh the most convnon options. Recommended for той users.
'"* М; j, ;i Support Service: it! LJ Meta Data Servi
РИС. 3.16. Создание нового представления в окне программы SQL Server Enterprise Manager
i При первом открытии диалогового окна Design View в его заголовке будут слова New I View, а не Design View.
Эти графические инструменты создания представлений можно использовать для создания запросов. Для этого щелкните правой кнопкой мыши на таблице базы данных и выберите из контекстного меню команду Open Table^Query (Открыть таблицуоЗап- ; рос). Созданный запрос нельзя сохранить, потому что отдельный запрос не является объектом базы данных SQL Server. Однако конструктор базы данных полезен для создания и тестирования хранимых процедур и извлечения отдельного набора данных. 3. Для открытия диалогового окна Add Table (Добавить таблицу) щелкните на кнопке Add Table с изображением плюса и таблицы или щелкните правой кнопкой мыши на пустом поле со схемой представления и выберите в контекстном меню команду Add Table.
Знакомство с SQL Server 2000
123
4. Выберите таблицу jobs и щелкните на кнопке Add (или дважды щелкните на таблице j obs) для включения таблицы j obs в представление. 5. Выберите таблицу employee и щелкните на кнопке Add (или дважды щелкните на таблице employee) для включения таблицы employee в представление. 6. Щелкните на кнопке Close, чтобы закрыть диалоговое окно Add Table. 7. Выберите поля в каждой таблице, т.е. поле job_desc в таблице jobs и поля fname и Iname в таблице employee. 8. Проверьте созданное представление, щелкнув на кнопке Run с изображением восклицательного знака или щелкнув правой кнопкой мыши на пустом поле со схемой представления, а затем выбрав из контекстного меню команду Run. Результат проверки созданного представления показан на рис. 3.17. У
г-—
l !л "
• • Q
! i* (All Columns)
L
У if name
I2lob_desc
~~~* *^^~^-~^-^_
i Imaxjvl
J Сей job.desc fname Iname
SC-^a-.
jobs employee employee
fouSunscrtType V у •
iy?.i 'name ^^^-лиз i jjob id [Ijobjvl
-ТЖсЖПойй
J -Y =£,
3
LiiJ M.U J5ELECT dbo.jobs.job desc, dbo.employee. fname, dbo. employee. Iname PROM dbo.empkiyee INNER JOIN dbo. jobs ON dbo. employee. job id» dbo. jobs. job id
il
job desc I/name Sales Representative Paolo Designer Pedro I Managing Edttor ; Victoria Editor " ' .l.Helen " ' Markerjng Manager i Lesley Chief Financial C^Ficier Francisco Chief Executive off cer PNfp .'.'.". __LJ Productions Manager Aria Business Operations Manager ; Arm Public Relations Manager Anabela
J
1
llname I Accorti APonsoj | Ashworth : Bennett . Brown Chang .Cr*mer"~.7."..".'. Cruz Devon Domingues
i
_^ -•
d
',;:•-
РИС. 3.17. Результаты создания и выполнения нового представления в окне конструктора представлений программы SQL Enterprise Manager 9. Сохраните новое представление, щелкнув на кнопке Save или щелкнув правой кнопкой мыши на пустом поле со схемой представления, а затем выбрав из контекстного меню команду Save. Для указания имени представления можно использовать соглашение об именах с суффиксом _view, например SpecialCustoraers_view. Это позволяет пользователям сразу же определить, что они имеют дело с представлением, а не с таблицей. Конечно, для этого можно использовать любое соглашение об именах, либо вообще не использовать его.
Глава 3
10. В диалоговом окне Save As (Сохранить как) введите имя представления и щелкните на кнопке ОК. Здесь можно указать любое имя, но в данном примере используется Employee Jobs_view. После создания представления Employee Jobs_view в базе данных появится еще один объект, которым можно манипулировать так же, как любой простой таблицей, несмотря на то что это результат объединения двух таблиц. Таким образом, можно получить более короткие и простые команды SQL на основе этого одного объекта, но по отношению к прежней корректно структурированной (нормализованной) базе данных. Аналогично можно создать представление на основе вычислений или манипуляций с данными таблицы. Предположим, что нужно извлечь имена сотрудников в виде одного поля с именем и фамилией в формате имя, фамилия. Для этого можно создать следующее представление: CREATE VIEW EmployeeNames_view AS SELECT Iname + ', ' + fname AS Name FROM employee
Использование представлений в приложениях Представление — это конструкция, которая позволяет управлять процессом извлечения информации из базы данных SQL Server. Это управление может осуществляться несколькими способами. В представлении можно ограничить количество строк или столбцов, что позволяет управлять данными, возвращаемыми пользователю. Для этого необходимо создать критерий отбора, который известен только разработчику базы данных, или предоставить пользователям доступ к данным на основе разрешений системы безопасности. Каждый объект базы данных— таблица, представление, хранимая процедура — может быть ассоциирован с пользователем или группой системы безопасности. В базах данных, которые используют преимущества представлений и хранимых процедур, прямой доступ к таблицам обычно ограничивается администратором базы данных. Клиентские приложения при этом ограничены только доступом к связанным представлениям или хранимым процедурам, которые, в свою очередь, отвечают за извлечение данных из основных таблиц. Создание скрытого поля — еще один способ ограничения доступа. При этом данные такого поля не возвращаются пользователю, а отфильтровываются с помощью представления. Клиентскому приложению даже не будет известно, что существуют еще какие-либо данные, поскольку оно будет ограничено лишь данными представления. Практически все профессиональные серверы баз данных SQL ограничивают непосредственный доступ к базе данных. Помимо ограничения доступа к строкам и полям, сокрытие таблиц баз данных с помощью представлений позволяет изменять их незаметно для клиентских приложений. Кроме этого, с помощью компонентов среднего уровня можно отделить изменения структуры базы данных от изменений бизнес-правил. Эти компоненты аналогичны представлениям и хранимым процедурам тем, что скрывают изменения структуры базы данных от клиентского приложения. Помимо этого, существует еще одно преимущество использования таких компонентов по сравнению с представлениями и хранимыми процедурам SQL Server: они упрощают процесс программирования, возвращают данные в виде объектов, а не строк и столбцов, а также не привязаны к
Знакомство с SQL Server 2000
конкретной СУБД или языку программирования. Более подробно компоненты среднего уровня рассматриваются в главе 12, "Web-службы и технологии промежуточного уровня".
Создание представления с помощью программы SQL Query Analyzer Для создания представлений можно использовать программу SQL Query Analyzer. Процесс создания представления в ней аналогичен подобному процессу в программе SQL Server Enterprise Manager, но обладает большей гибкостью, несмотря на использование более скромных графических инструментов. Для создания представления tblEmployee без конфиденциального поля Salary в программе SQL Query Analyzer выполните приведенные ниже действия. 1. Введите в окно программы SQL Query Analyzer следующий код (он организован таким образом, чтобы представление создавалось независимо от того, существует оно уже или нет): USE novelty GO
DROP VIEW GO
Employee_view
CREATE VIEW Employee_view AS SELECT ID, FirstName, LastName, DepartmentID FROM tblEmployee GO
SELECT * FROM Employee_view 2. Для выполнения этой последовательности команд нажмите клавишу или щелкните на кнопке Execute Query. Представление будет создано и запущено, а результаты будут показаны во вкладке Grids (или Results). 3. Проверьте работоспособность представления с помощью программы SQL Server Enterprise Manager, в которой нужно выбрать вкладку Views для базы данных Novelty. НА ЗАМЕТКУ
Ранее в этой главе рассматривалось, как создать представление графическими '. | средствами в программе SQL Server Enterprise Manager, щелкая на нем правой кноп! кой мыши и выбирая команду Design View (Создать представление) из контекстного j | меню. Текст команды SQL для создания представления можно редактировать, дваж- | | ды щелкнув на представлении и изменяя этот текст в диалоговом окне. В рассматриваемом примере, кроме создания представления с помощью программы SQL Server Enterprise Manager, демонстрируется удобство использования пакетов команд SQL. Приведенный выше пакет команд SQL не только создает новое представление, но и связывает его с нужной базой данных и извлекает данные для него. Полученный результат подтверждает, что представление работает именно так, как и предполагалось.
Глава 3
Пакеты можно создавать для упрощения процесса создания объектов базы данных с помощью программы SQL Server Enterprise Manager, потому что в большинстве случаев при создании объектов базы данных приходится выполнять сразу несколько операций. Типичным примером пакета команд SQL является удаление старой таблицы, создание новой таблицы и наполнение ее данными. Кроме этой и других задач, пакет команд SQL может использоваться для проверки наличия учетной записи и создания учетной записи с используемым по умолчанию паролем.
Создание и запуск хранимых процедур С помощью представления можно контролировать данные, возвращаемые SQL Server, однако существует еще более мощное средство— хранимые процедуры (storedprocedures). Хранимые процедуры подобны представлениям, но могут выполнять более сложные операции над данными. Например, с помощью хранимых процедур можно выполнять следующие операции: • вычисления; • установка или возврат параметров; •
реализация логики приложения, для чего требуется выполнить несколько этапов или запросов с помощью языка программирования, предназначенного для использования с базой данных;
•
возврат данных в форме, которая наилучшим образом подходит для приложения-клиента.
Заметьте: не все эти операции можно выполнить с помощью представлений. Хранимую процедуру можно представить себе как особый вид процедуры, так как она хранится в самой базе данных, а не является частью приложения, которое выполняется на клиентском компьютере или прикладном сервере (именно поэтому она так и называется). В предыдущем списке операций указано, что хранимая процедура может содержать не только простой однострочный запрос, но и сложный многострочный запрос, который способен выполнить несколько действий, прежде чем возвратить результат. Хранимые процедуры создаются на специальном языке программирования, который применяется в используемой базе данных. Этот язык содержит практически все распространенные программные конструкции, хотя его синтаксис не всегда очевиден. В SQL Server для создания хранимых процедур используется язык Transact SQL.
; I j