Основные команды sql. Синтаксис и справка по командам sql Microsoft sql server команды

История SQL

Стандарты SQL

Основные команды SQL

Обработка команд SQL сервером Oracle

Стадии выполнения команды SQL

Выполнение команды DML

Выполнение команды SELECT

Выполнение команд DDL

Литература

Все операции над данными реляционной базы данных выполняются посредством языка доступа к данным, являющимся стандартным языком для систем управления реляционными базами данных. Таким стандартным языком является SQL Structured Query Language (структурированный язык запросов).

Язык структурированных запросов SQL

История SQL

Статья Кодда в 1970 году вызвала большой поток исследований, связанных с реляционными базами данных. Для реализации реляционной модели, фирма IBM в 1974 году начала разработку большого исследовательского проекта, названного System/R. Цель этого проекта заключалась в том, чтобы доказать работоспособность реляционной модели и приобрести опыт реализации реляционной СУБД.

В 1974 – 1975 годах на первом этапе выполнения проекта System/R был создан минимальный прототип реляционной системы управления базами данных. В это же время вышла первая статья с описанием языка запросов к базе данных, названного SEQUEL – Structured English Query Language (структурированный английский язык запросов).

В 1978 – 1979 годах на втором этапе выполнения проекта полностью переделанная реализация System/R была установлена на компьютерах нескольких заказчиков фирмы IBM для опытной эксплуатации. Эта эксплуатация принесла первый опыт работы с реляционной СУБД и с языком базы данных, который был переименован в SQL – Structured Query Language (структурированный язык запросов). Несмотря на изменение названия, произношение «сиквел» сохранилось и по сегодняшний день.

В 1979 году исследовательский проект System/R закончился, и IBM сделала заключение, что реляционные базы данных не только работоспособны, но и могут служить для создания коммерческих продуктов.

Стандарты SQL

В 1982 году началась работа над официальным стандартом SQL. В 1986 году стандарт был утвержден Американским институтом национальных стандартов (American National Standards Institute – ANSI) под номером X3.135, а в 1987 году – как стандарт Международной организации по стандартам (International Standards Organization – ISO). Этот стандарт, пересмотренный в 1989 году, обычно называют стандартом «SQL-89» или «SQL1».

Многие из членов комитетов ANSI и ISO представляли различные фирмы – разработчики СУБД, в каждой из которых был реализован собственный диалект SQL. Эти диалекты были, в основном, похожи друг на друга, однако несовместимы в деталях. Поэтому комитет не стандартизовал некоторые части языка, определив, что они реализуются по усмотрению разработчика. Это позволило объявить большую часть реализаций SQL совместимой со стандартом, но сделало сам стандарт относительно слабым.

Чтобы исправить эту ситуацию, комитет ANSI создал проект более жесткого стандарта «SQL2» и «SQL3». Эти стандарты оказались более противоречивыми, чем исходный стандарт, т.к. предусматривали возможности, выходящие за рамки уже существующих программных продуктов, использующих SQL. Тем не менее, стандарт «SQL2», был окончательно принят комитетом ANSI в 1992 году.

Все существующие коммерческие продукты поддерживают, несмотря на стандарт SQL2, собственный диалект языка SQL. Однако ядро SQL стандартизировано достаточно жестко, и поставщики СУБД пытаются привести свои продукты в соответствие со стандартом.

Основные команды SQL

Итак, SQL – структурированный язык команд для взаимодействия с сервером реляционных баз данных из любого инструментального пакета или приложения. Администратор базы данных использует язык запросов для формирования и обслуживания баз данных, а пользователь – для доступа к данным.

Возможности SQL:

§ Подходит разным пользователям, включая пользователей с самым малым опытом программирования, т.к. является достаточно простым и наглядным языком

§ Является непроцедурным языком. Пользователи описывают с помощью языка SQL то, что они хотят сделать, а компилятор SQL автоматически генерирует процедуры для навигации по базе данных и выполнения требуемой задачи

§ Сокращает время, необходимое для создания и сопровождения систем, т.к. является единым языком и для определения объектов, и для манипулирования данными

Несмотря на то, что Oracle SQL совместим со стандартом, некоторые свойства SQL2 не поддерживаются Oracle или отличаются от стандарта.

Команды SQL можно разделить на несколько категорий:


Команды

Описание

Язык манипулирования данными ( DML)
Запрашивают или манипулируют данными в объектах базы данных

Извлекает данные из одной или более таблиц или представлений

Добавляет новые строки в таблицу

Изменяет значения колонок в существующих строках таблицы

Удаляет строки из таблиц

Накладывает блокировку на таблицу или представление, временно ограничивая доступ к объекту других пользователей

Позволяет просмотреть план выполнения SQL-утверждения

Язык определения данных (DDL) базы данных

Определяют, изменяют определение или удаляют из словаря определение объектов базы данных

Используются для создания структур данных.

Используются для изменения структур данных.

Используются для удаления структур данных.

Изменяет имена объектов

Усекает объекты (удаляет все строки, оставляя определение объекта)

Собирает статистики об объектах, проверяет структуру объектов

Добавляет комментарии объектам в словарь данных

Команды управления транзакциями

Управляют изменениями, сделанными командами DML и группируют команды DML в одну транзакцию

Подтверждает изменения

Отменяет изменения до состояния данных на начало транзакции или до точки сохранения

Устанавливает точки сохранения, до которых можно отменить изменения

SET TRANSACTION *

Устанавливает свойства транзакции

Язык управления доступом ( DCL)

Предоставляют или отменяют права доступа к базе данных Oracle и ее структурам

Предоставляет права доступа к базе данных Oracle и ее структурам

Отменяет права доступа к базе данных Oracle и ее структурам

Программный SQL

Позволяет выполнять команды SQL из программных модулей

Определяет явный курсор

Открывает курсор

Выбирает строку из курсора

Закрывает курсор

Извлекает данные из одной или более таблиц в программные переменные

EXECUTE IMMEDIATE *

Динамически выполняет оператор SQL

* - Не являются частью стандарта ANSI/ISO, но используются в СУБД Oracle

Обработка команд SQL сервером Oracle

Команды SQL проходят несколько стадий при обработке сервером Oracle. В процессе обработки задействованы различные процессы и структуры памяти Oracle (Рисунок 1).

Рисунок 1 Процессы и структуры памяти, участвующие в обработке команд SQL

· Команды SQL обрабатываются серверным процессом

· Идентичные команды SQL (дерево разбора и план выполнения) хранятся в одних и тех же разделяемых областях SQL разделяемого пула . Разделяемый пул располагается всегда в системной глобальной области . Команды SQL считаются идентичными, если:

o Их текст полностью идентичен, вплоть до регистра и количества пробелов

o Они ссылаются на одни и те же объекты

o Типы и имена используемых переменных совпадают

Запрос (query) - это команда базы данных, осуществляющая выборку записей. Используя запросы, можно получить данные из одного или нескольких полей, принадлежащих одной или нескольким таблицам. При этом данные можно отбирать в соответствии с определенными условиями, называемыми критериями, которые служат для ограничения общего объема отбираемых данных.

Запросы в Visual Basic . NET обычно основаны на SQL. Это стандартный язык для осуществления выборки информации и других операций над базами данных. Он прост в освоении и реализован во многих различных базах данных, поэтому при желании преобразовать свое приложение управления базой данных SQL Server, например, в Sybase или Oracle вам не придется заново изучать совершенно новый язык запросов.

Однако все это теория. А на практике каждый производитель базы данных имеет собственный способ реализации стандарта (так называемый промышленный стандарт), и Microsoft в этом смысле не является исключением. Хотя реализация SQL в СУБД SQL Server радикально не отличается от реализаций прочих производителей, вы должны знать, что существуют и другие диалекты языка 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. Выберите команду меню Query→Run (Запрос→Запуск), и нижняя панель результатов выполнения запроса будет иметь вид как на рис. 2.2.

Созданный запрос можно сохранить для последующего использования. Сохраненные в базе данных запросы называются представлениями (views). Их можно использовать точно так же, как обычные таблицы базы данных. Они позволяют упростить работу со сложными базами данных, особенно если запросы включают несколько соединенных таблиц (как будет показано далее в главе).

РИС. 2.1. Диалоговое окно режима создания представления

РИС. 2.2. Диалоговое окно режима создания представления после запуска запроса


Для сохранения представления в среде Visual Studio .NET выберите команду меню File→Save View1, и Visual Studio .NET предложит ввести новое имя для данного представления. Укажите для него имя qryCustomerList. После этого представление будет сохранено в базе данных и его могут использовать другие разработчики, которым нужно получить доступ к базе данных.

НА ЗАМЕТКУ

Вы уже, наверное, заметили, что для таблиц и представлений используется простое соглашение об именах, основанное на присвоении префиксов tbl и qry именам объектов базы данных. Тому есть две причины. Во-первых, это упрощает определение типа объекта базы данных, потому что в некоторых ситуациях это может быть не совсем очевидно. Во-вторых, такое соглашение об именах использовалось в прежних изданиях этой книги и поддерживается здесь для преемственности.

Наше соглашение об именах уже знакомо программистам, которые имеют опыт работы с Microsoft Access. Хотя представленные здесь действия выполняются несколько иначе, чем к тому привыкли программисты, имеющие опыт работы с SQL Server, мы считаем, что наличие какого-либо соглашения об именах все же лучше, чем его отсутствие. Конечно, в своей работе вы можете использовать какое-то другое соглашение об именах.

В следующих разделах диалоговое окно режима создания представления будет использовано для создания запросов на выборку данных.

Отбор записей с помощью предложения SELECT

Предложение SELECT является основой каждого запроса, предназначенного для выборки данных. Оно указывает процессору баз данных, какие поля требуется возвратить. Общая форма предложения SELECT имеет следующий вид:

А его содержание таково: "Вернуть значения всех полей, найденных в указанном источнике записей". Эта форма команды удобна тем, что вам не обязательно знать имена извлекаемых полей таблицы. Однако выборка всех полей таблицы может быть не рациональной, особенно в том случае, когда требуется только два поля, в то время как такой запрос осуществляет выборку двух десятков полей.

Кроме команды, передаваемой процессору базы данных на возврат всех полей источника записей, можно задать конкретный перечень необходимых при отборе полей. Такое ограничение может улучшить эффективность выполнения запроса, особенно для больших таблиц, содержащих много полей, так как в этом случае отбираются только нужные поля.

Ниже приводится пример предложения SELECT, которое извлекает из базы данных значения только двух полей таблицы- FirstName и LastName, содержащих имя и фамилию клиента.

SELECT ,

Обратите внимание также на то, что предложение SELECT не готово к выполнению без предложения FROM (поэтому примеры предложения SELECT, приведенные в этом разделе, выполнить в таком виде нельзя). Чтобы полнее ознакомиться с предложениями SELECT, просмотрите примеры использования предложения FROM, приведенные в следующем разделе.

Предложение FROM указывает на источник записей, из которого запрос извлекает записи. Этим источником может быть как таблица, так и другой хранимый запрос. У вас также есть возможность отбора записей из нескольких таблиц, которая подробно рассматривается далее, в разделе об объединении нескольких таблиц в одном запросе.

Предложения FROM работают совместно с предложениями SELECT. Например, чтобы отобрать все записи в таблице tblCustomer, используйте приведенную ниже команду SQL.

При выполнении этого запроса считываются все записи и все поля в таблице tblCustomer (без какого-либо упорядочения записей).

Чтобы отобрать только имя и фамилию клиентов, воспользуйтесь приведенной ниже командой SQL.

SELECT FirstName, LastName FROM tblCustomer

После изменения запроса в режиме конструктора представления выберите команду Query→Run (Запрос→Запуск) для обновления результатов выполнения запроса, которые теперь будут иметь такой вид, как на рис. 2.3.

РИС. 2.3. Результаты выполнения запроса на выборку данных из полей FirstName и LastName таблицы tblCustomer


Из соображений эффективности всегда ограничивайте число полей в предложении SELECT только теми полями, которые могут потребоваться вашему приложению. Обратите внимание, что записи, отобранные запросом SELECT FROM, в результирующем наборе не упорядочены. Если не задать порядок сортировки (использование предложения ORDER BY рассматривается ниже в этой главе), записи всегда возвращаются в неопределенном порядке.

Предложение WHERE указывает процессору базы данных на необходимость ограничения количества отбираемых записей согласно одному или нескольким заданным критериям. Критерий - это логическое выражение, результатом оценки которого является либо "истина" (true), либо "ложь" (false). В языке SQL существует много аналогичных выражений эквивалентности, знакомых пользователям Visual Basic (например: >0 и =" Smith ").

Предположим, вам нужно отобрать только тех заказчиков, которые проживают в Калифорнии (СА). Для этого можно использовать приведенный ниже запрос SQL.

SELECT FirstName, LastName, State FROM tblCustomer

В результате выполнения этого запроса будет извлечена запись с данными о клиенте с именем Daisy Klein.

Обратите внимание также на то, что для обозначения текстовой строки в предложении WHERE используется одиночная кавычка. Подобное обозначение удобно тем, что отличается от обозначения текстовой строки в Visual Basic двойной кавычкой, а инструкции SQL иногда встраиваются в код Visual Basic.

Можно создавать более сложные предложения WHERE, связывая два и более критерия с помощью логических операторов AND или OR. Например, необходимо отобрать всех клиентов, проживающих в городе Денвер (Denver) штата Колорадо (СО), т.е. вас не интересуют те клиенты, которые проживают в других городах этого штата. Для этого нужно задать два критерия и связать их оператором AND, как показано в приведенном ниже примере.

WHERE (State = "CO") AND (City = "Denver")

В результате выполнения этого запроса будет извлечена запись с данными о клиенте с именем ThurstonRyan, который живет в городе Денвер, штат Колорадо. Если в этом городе живут другие клиенты, то в результате выполнения данного запроса будут извлечены записи с информацией о них. Однако при этом не будут извлекаться сведения о клиентах, которые проживают в городах с тем же названием, но в других штатах.

Если вас интересует информация о клиентах в штатах Вашингтон (WA) и Калифорния (СА), воспользуйтесь оператором OR, чтобы связать два критерия, как показано ниже.

SELECT FirstName, LastName, City, State
WHERE State = "CO" OR State = "CA"

В результате выполнения этого запроса будут извлечены три записи с данными о клиентах в штатах Вашингтон и Калифорния. Из сказанного выше следует, что для отбора данных из таблицы с помощью условий AND и OR можно составить практически любую комбинацию критериев в предложении WHERE.

НА ЗАМЕТКУ

Ключ к успешной разработке приложений клиент/сервер – выработка такой тактики, согласно которой приложение-клиент не заказывало бы слишком много записей в одной выборке. Это гарантирует, что приложения будут выполняться быстро и компьютеры ваших пользователей не зависнут. Залог успеха вашей работы - рациональное использование предложения WHERE.

При построении предложения WHERE можно использовать операторы, перечисленные в табл. 2.1.

Таблица 2.1. операторы, используемые в предложении WHERE

Оператор Функция
< Меньше
<= Меньше или равно
> Больше
>= Больше или равно
= Равно
<> Не равно
BETWEEN Внутри диапазона значений
LIKE Соответствует образцу
IN Входит в список значений

Оператор BETWEEN

Этот оператор возвращает все записи, значения которых лежат внутри определенных вами границ. Например, для того чтобы отобрать все заказы, оформленные за период с 4 января по 5 июня 2001 года, необходимо написать приведенную ниже инструкцию SQL.

WHERE OrderDate BETWEEN "1/4/2001" AND "6/5/2001"

В результате выполнения этого запроса будут извлечены записи, показанные на рис. 2.4.

Обратите внимание, что значения даты в SQL Server обозначаются символом одиночной кавычки. Разработчикам, которые имеют опыт работы с датами в Microsoft Access и привыкли использовать для этого символ #, придется учесть это новшество и заменить символы # одиночными кавычками.

РИС. 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

В результате выполнения этого запроса будут извлечены записи для тех клиентов, фамилии которых начинаются с буквы J.

При создании шаблонов можно также использовать символ подчеркивания. Он занимает место только одного символа в шаблоне. Например, чтобы отобрать всех клиентов, у которых почтовый индекс состоит из пяти цифр и начинается с числа 80, воспользуйтесь следующей командой SQL:

SELECT ID, FirstName, LastName, Address, PostalCode

В результате выполнения этого запроса будут извлечены записи для тех клиентов, почтовый индекс которых начинается с числа 80.

Оператор LIKE можно использовать также для отбора записей на основе вхождения в диапазон определенных алфавитных или числовых значений. Например, чтобы возвратить список клиентов, фамилии которых начинаются с букв в диапазоне от А до М, используйте приведенную ниже команду SQL.

В результате выполнения этого запроса будут извлечены пять записей для тех клиентов, фамилии которых начинаются с букв в диапазоне от А до М.

НА ЗАМЕТКУ

Действие символов подстановки в Microsoft Access отличается от действия этих же символов в стандартном SQL. В Microsoft Access символ звездочки используется вместо символа процента для подбора любого числа произвольных символов, а символ знака вопроса – вместо символа подчеркивания для подбора любого одиночного символа. В стандартном SQL символ подчеркивания используется для подбора i любого числа произвольных символов, а символ процента – для подбора любого одиночного символа.

Оператор IN

Этот оператор используется для отбора записей, которые соответствуют элементам из заданного списка значений. Например, чтобы отобрать всех клиентов в штатах Колорадо (СО) или Висконсин (WI), воспользуйтесь приведенной ниже инструкцией SQL.

SELECT FirstName, LastName, State

В результате выполнения этого запроса будут извлечены три записи для тех клиентов, которые живут в штатах Колорадо или Висконсин. Как видите, с помощью оператора IN можно получить те же результаты, что и с помощью оператора OR. Некоторые разработчики предпочитают применять оператор IN при использовании нескольких критериев, поскольку в таком случае команда SQL выглядит более аккуратно.

Сортировка результатов с помощью предложения ORDER BY

Предложение ORDER BY формирует для процессора баз данных команду на сортировку отобранных записей. Можно сортировать по любому полю или нескольким полям, причем как в возрастающей, так и в убывающей последовательности. Для чтобы задать порядок сортировки, добавьте в конец обычного запроса SELECT предложение ORDER BY, а за ним укажите поле или поля, по которым нужно выполнить сортировку. Например, чтобы отобрать список клиентов, отсортированный по фамилии, воспользуйтесь приведенной ниже инструкцией SQL.

SELECT ID, FirstName, LastName

В результате выполнения этого запроса из таблицы tblCustomer будут извлечены все записи, упорядоченные по фамилиям клиентов.

Сортировка в убывающей последовательности

Для сортировки в убывающей последовательности задайте ключевое слово после имени поля, по которому проводится сортировка. Например, если нужно отобрать из таблицы tblOrder записи так, чтобы сначала располагались самые последние заказы, воспользуйтесь следующей командой SQL:

В результате выполнения этого запроса из таблицы tblOrder будут извлечены все записи, причем сначала будут располагаться самые последние заказы.

Сортировка по нескольким полям

Для того чтобы отсортировать записи по нескольким полям, после предложения ORDER BY перечислите поля друг за другом через запятую. Например, чтобы отсортировать записи в таблице tblCustomer по фамилии, а затем по имени, воспользуйтесь приведенной ниже командой SQL.

SELECT FirstName, LastName, City, State

В результате выполнения этого запроса из таблицы tblCustomer будут извлечены все записи, отсортированные по фамилиям, а затем по именам (например, за клиентом Betty Klein будет располагаться клиент Daisy Klein).

Отображение первых или последних записей диапазона с помощью предложения ТОР

Ключевое слово ТОР используется для отображения некоторого количества начальных или конечных записей из большого результирующего набора. Для ограничения числа записей в результирующем наборе ключевое слово ТОР в запросах сочетается с предложением, указывающим порядок сортировки. Причем ключевое слово ТОР можно комбинировать как с числом, означающим количество записей, так и с числом, означающим процентное содержание отображаемых записей.

Например, необходимо отобрать три наиболее крупных заказа из числа последних заказов в таблице tblOrder. Для этого воспользуйтесь приведенной ниже инструкцией SQL.

SELECT ID, OrderDate, CustomerID

Обратите внимание, что ключевое слово DESC сортирует результирующий набор по убыванию. В результате выполнения этого запроса из таблицы tblOrder будут извлечены сведения о заказах каждого клиента, причем сначала будут располагаться самые последние заказы. Все просто прекрасно, за исключением того, что в базе данных, которая хранит информацию обо всех когда-либо выполненных заказах, придется просмотреть тысячи записей, в то время как вас интересуют только три наиболее крупных заказа. Поэтому вместо предыдущей команды попробуйте выполнить приведенную ниже инструкцию SQL.

В результате выполнения этого запроса из таблицы tblOrder будут извлечены три записи для наиболее крупных заказов.

Почему же запрос вернул четыре записи вместо запрошенных трех? Такой запрос (ТОР 3) вовсе не гарантирует, что будут возвращены только три записи. Возможно, что результирующий набор будет содержать одну или две записи (или даже ни одной), если в таблице содержится только такое количество записей. А если на последнее место в результирующем наборе претендуют две и более записи, то вполне возможно, что будут возвращены четыре или даже большее количество записей.

В синтаксисе SQL нет понятия BOTTOM N, но зато есть возможность возвратить заданное количество последних записей в таблице. Для того чтобы создать такой запрос, достаточно отсортировать записи в возрастающей последовательности (т.е. от самого малого значения к самому большому), как показано ниже.

Этот запрос показывает три самых "древних" заказа в базе данных.

Сортировка данных в порядке возрастания в SQL принимается по умолчанию. Поэтому нет необходимости использовать ключевое слово ASC для задания порядка сортировки по возрастанию.

Создание запросов TOP PERCENT

Можно писать запросы, возвращающие записи, количество которых определяется заданным процентом от общего количества записей в таблице. Например, если у вас есть таблица с 1000 записей и необходимо возвратить один процент первых записей, то, как правило, будет отображено 10 записей. (Возможно, будет отображено более 10 записей, если несколько записей имеют одинаковое значение. Такой же случай рассматривался и для запроса ТОР N.)

Для возврата первых записей в результирующий набор, количество которых задано процентным отношением к общему количеству записей в таблице, используется предложение TOP N PERCENT. Например, чтобы отобрать первые 20% от неоплаченных заказов в таблице tblOrder, воспользуйтесь приведенной ниже командой SQL.

В результате выполнения этого запроса из таблицы tblOrder будут извлечены две записи для самых последних заказов, которые составляют 20% от 10 строк таблицы tblOrder.

Объединение связанных таблиц в запросе

Для выборки связанной информации из нескольких таблиц используется объединение (join). Чтобы создать объединение в запросе, необходимо определить первичные (primary) и внешние (foreign) ключи в таблицах, участвующих в объединении (эти понятия обсуждаются в главе 1, "Основы построения баз данных"). Например, рассмотрим две связанные таблицы с показанными ниже структурами.

tblCustomer
ID
FirstName
LastName
Address
City
State
PostalCode
Phone
Fax
Email
tblOrder
ID
CustomerID
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
...

Такой результирующий набор нетрудно получить, используя объединение, несмотря на то что необходимые данные хранятся в разных таблицах. Можно надеяться на получение нужных данных, если сообщить процессору баз данных о том, что первичный ключ таблицы tblCustomer(ID) связан с внешним ключом ((CustomerID)) таблицы tblOrder.

НА ЗАМЕТКУ

Обратите внимание, что в этом результате объединения один и тот же клиент отображен дважды, хотя его имя было введено в базу данных один раз. Это значит, что клиент имеет несколько заказов. Иными словами, при нескольких заказах одного и того же клиента вам не пришлось вводить в базу данных информацию об этом клиенте несколько раз. Вместе с тем в результате выполнения запроса иногда можно получить избыточную информацию. Для исправления такой ситуации можно применять несколько разных методов.

Выражение объединения в SQL

В SQL Server объединение можно установить с помощью выражения эквивалентности между двумя полями, например:

Этот запрос SQL возвращает информацию обо всех клиентах, которые имеют заказы в таблице tblOrder. В результате выполнения запроса возвращаются три столбца данных: поля FirstName и LastName из таблицы tblCustomer, а также поле OrderDate из таблицы tblOrder.

Обратите внимание, что в запросе с объединением таблиц при использовании полей, имеющих одинаковые имена, но принадлежащих разным таблицам, необходимо перед именем поля вставлять ссылку на соответствующую таблицу (например, tblOrder.ID вместо ID). В большинстве случаев при использовании конструктора представлений в среде Visual Studio .NET для создания запроса интегрированная среда разработки способна определить выполняемые действия и дополнить выражение недостающими частями. Как уже сообщалось ранее, в данной книге примеры инструкций SQL приводятся в наиболее кратком виде, а необязательные части применяются только в случае необходимости.

Использование конструктора представлений для создания объединений

Поскольку создание объединений может составлять самую сложную часть запросов, особенно когда задействовано более двух таблиц, неплохо было бы при создании таких запросов иметь некоторое подспорье. К счастью, в Visual Basic предусмотрен конструктор представлений (View Designer), благодаря которому создание запроса с объединением нескольких таблиц значительно упрощается. При использовании конструктора представлений нет необходимости запоминать сложный синтаксис объединения в SQL. Вместо этого можно создать объединение графическим путем, выполнив приведенные ниже действия.

1. В окне Server Explorer создайте новое представление для базы данных Novelty.

2. После этого появится диалоговое окно Add Table (Создать таблицу), в котором следует указать таблицы tblCustomer и tblOrder, а затем щелкнуть на кнопке Close. Схема представления в окне конструктора представлений показана на рис. 2.5.

РИС. 2.5. Создание объединения двух таблиц в окне конструктора представлений

Обратите внимание на то, что конструктор представлений автоматически создает объединение между двумя таблицами на основе известного ключевого поля ID в таблице tblCustomer и явно заданного ранее отношения с полем CustomerID в таблице tblOrder.

После выполнения запроса на основе объединения двух таблиц в окне конструктора представлений будут отображены извлеченные данные, как показано на рис. 2.6.

Использование внешних объединений

Обычное (внутреннее) объединение (inner join) возвращает записи из двух таблиц, если значение первичного ключа первой таблицы соответствует значению внешнего ключа второй таблицы, связанной с первой. Предположим, необходимо получить все записи из одной таблицы, участвующей в объединении, вне зависимости от того, существуют ли связанные записи в другой таблице. В этом случае необходимо использовать внешнее объединение (outer join).

Например, для извлечения списка клиентов и заказов, в который включены также клиенты, не имеющие неоплаченных заказов, можно использовать приведенный ниже запрос.

SELECT FirstName, LastName, OrderDate
FROM tblCustomer LEFT OUTER JOIN
tblOrder ON tblCustomer.ID = tblOrder.CustomerID

Обратите внимание, что в предложении LEFT JOIN используется синтаксис имя_таблицы.имя_поля. Более длинное имя позволяет избежать неоднозначности при использовании полей с одинаковыми именами, поскольку поле ID существует как в так и в tblOrder. Фактически предложение LEFT OUTER JOIN означает, что будут отображены все данные таблицы tblCustomer, которая находится в левой стороне выражения tblCustomer.ID = tblOrder.CustomerID.

РИС. 2.6. Выполнение запроса на основе объединения двух таблиц в окне конструктора представлений

Этот запрос возвращает приведенный ниже набор записей.

FirstName LastName OrderDate
John Smith 1/4/2001
John Smith 1/9/2001
Jill Azalia 1/14/2001
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

В этот результирующий набор включены все клиенты базы данных, независимо от того, имеют ли они заказы или нет. Для клиентов, не имеющих заказов, в поле OrderDate появится , что означает отсутствие данных.

Правое внешнее объединение (right join) аналогично левому внешнему объединению (left join) , за исключением того, что оно возвращает все записи из второй таблицы, участвующей в объединении (имеется в виду таблица с правой стороны), независимо от того, есть ли соответствующие им записи в первой таблице (расположенной с левой стороны). (Левое и правое объединения являются разновидностями внешнего объединения и в определенных обстоятельствах могут возвращать идентичные результаты.)

Выполнение вычислений в запросах

В строках запроса допускается выполнение вычислений. Для этого нужно просто заменить имя поля в предложении SELECT именем арифметического выражения. Допустим, вам нужно создать запрос для вычисления налога с продаж для складских запасов (сведения о которых хранятся в таблице tblItem). В приведенном ниже запросе SQL вычисляется налог с продаж с учетной ставкой 7,5% для каждого товара.

SELECT ID, Item, Price, Price * 0.075 AS SalesTax

После выполнения этого запроса будут получен показанный ниже результат.

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 3.99 0.29925
5 Invisible Ink 2.29 0.17175
6 Loaded Dice 3.49 0.26175
7 Whoopee Cushion 5.99 0.44925

Поскольку в этих вычислениях фигурируют деньги, конечный результат нужно округлить до двух десятичных знаков. К счастью, в SQL Server для этого предусмотрена специальная функция ROUND, которая позволяет очень легко выполнить это. Обычно ее используют с указанием двух параметров: собственно десятичного числа и точности, выраженной в виде количества знаков после запятой. Вот как выглядит запрос с функцией ROUND:

SELECT Name, Retail Price, ROUND (Retail Price + 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,
tblInventory.RetailPrice * tblOrderTime.Quantity AS ExtendedPrice
tblInventory ON tblOrderTime.ItemID = tblITem.ID
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

Обратите внимание, что данные в поле ExtendedPrice не хранятся в базе данных, они вычислены "на лету".

Запросы, которые группируют данные и подводят итоги

Часто требуется создавать запросы, подобные следующему: "Сколько заказов поступило вчера?" При этом вас не интересует, кто оформил заказ, вы только хотите знать количество вчерашних заказов. Это можно сделать, используя запросы, группирующие итоговые функции.

Запросы с группировкой подводят итоги по одному или нескольким полям. Например, если вам интересно увидеть число заказов для каждого клиента, то нужно создать приведенный ниже запрос для таблицы tblOrder с группировкой данных по полю CustomerID.

SELECT CustomerID, COUNT(CustomerID) AS TotalOrders

Результат выполнения такого запроса приведен ниже.

CustomerID TotalOrders
1 2
2 1
4 3
5 1
7 1
8 2

Обратите внимание на использование предложения AS в этом выражении SQL. Оно предназначено для присвоения имени столбцу, содержащему результат итоговой функции, поскольку этот результат вычисляется, а не хранится в базе данных.

Для отображения имен клиентов вместо их идентификаторов нужно просто объединить с результатами запроса данные из таблицы tblCustomer.

SELECT tblOrder.CustomerID, FirstName, LastName
FROM tblOrder INNER JOIN tblCustomer
ON tblOrder.CustomerID = tblCustomer.ID

После выполнения такого запроса будет получен приведенный ниже результат.

CustomerID FirstName LastName TotalOrders
1 John Smith 2
2 Jill Azalia 1
4 Daisy Klein 3
5 Dave Martin 1
7 Thurston Ryan 1
8 Jane Winters 2

В этом случае предложение GROUP BY содержит поле CustomerID вместе с объединенными полями FirstName и LastName из таблицы tblCustomer. При использовании предложения GROUP BY в него необходимо включить все поля, по которым группируются извлекаемые записи. В данном случае идентификатор клиента и его имя участвуют в группировании данных и потому присутствуют в предложении GROUP BY. (К счастью, если вы забудете выполнить эту операцию, среда Visual Studio .NET автоматически предложит вам сделать это.)

Применение предложения HAVING для группирования данных в запросах

Как уже отмечалось выше, критерий запроса служит для ограничения количества извлекаемых записей. В обычных запросах для включения критериев используется предложение WHERE, в запросах с группированием - предложение HAVING. Эти предложения применяются совершенно одинаково, за исключением того, что HAVING относится к агрегированным строкам (т.е. к результату группирования), a WHERE – к отдельным строкам. Это довольно незначительное отличие, потому что в 9 случаях из 10 они дают совершенно одинаковый результат. Например для создания отчета о продажах клиента Jane с группированием данных можно использовать приведенный ниже запрос.

COUNT(dbo.tblOrder.CustomerID) AS TotalOrders
FROM tblOrder INNER JOIN tblCustomer
ON tblOrder.CustomerID = tblCustomer.ID
GROUP BY FirstName, LastName, CustomerID

Этот запрос возвращает одну запись для клиента Jane Winters с указанием двух сделанных ею заказов. Допустим, теперь нужно получить список активных покупателей, т.е. клиентов, сделавших более одного заказа. Поскольку агрегированное количество заказов хранится в вычисленном поле TotalOrders, можно предположить, что для определения таких клиентов допустимо использовать выражение HAVING TotalOrders > 1. К сожалению, это выражение некорректно, так как TotalOrders – это не поле базы данных, а вычисленное поле. Вместо этого следует включить данное вычисление в предложение HAVING показанного ниже запроса.

SELECT tblOrder.CustomerID, FirstName, LastName,
COUNT(dbo.tblOrder.CustomerID) AS TotalOrders
FROM tblOrder INNER JOIN tblCustomer
ON tblOrder.CustomerID = tblCustomer.ID
GROUP BY FirstName, LastName, CustomerID
HAVING (COUNT(tblOrder.CustomerID) > 1)

После выполнения этого запроса будут получены три строки, каждая из которых содержит номер, имя, фамилию и количество заказов для каждого клиента, который сделал более одного заказа.

CustomerID FirstName LastName TotalOrders
1 John Smith 2
4 Daisy Klein 3
8 Jane Winters 2

Функция SUM

Ваши возможности в подведении итогов не ограничены простым подсчетом записей. Используя функцию SUM, можно генерировать итоговые результаты для всех возвращаемых записей по любым числовым полям. Например, для создания запроса, который генерирует итоги по количеству заказанных товаров каждым клиентом, необходимо написать следующую команду SQL:

SELECT OrderID, SUM(Quantity) AS TotalItems

Этот запрос возвращает приведенный ниже результирующий набор.

OrderID TotalItems
1 6
2 2
3 1
4 23
5 4
6 13
7 12
8 3
9 4
10 4

Как и в предыдущих примерах группирования, если вы захотите извлечь дополнительную связанную информацию (например, имя и фамилию клиента), следует использовать объединение с другой таблицей. Помните, что для агрегирования данных потребуется сгруппировать данные по крайней мере по одному полю.

Перечень итоговых функций

В табл. 2.2 перечислены все итоговые функции, доступные в SQL.

Таблица 2.2. Итоговые функции SQL


Синтаксис этих функций, по сути, соответствует синтаксису функции COUNT, которая рассматривалась в предыдущем разделе. Например, для ежедневного вычисления среднего количества товаров в каждом заказе воспользуйтесь приведенным ниже запросом SQL.

SELECT AVG(tblOrderItem.Quantity) AS AverageLineItemQuantity
tblOrderItem ON tblOrder.ID = tblOrderItem.OrderID

Этот запрос возвращает значение 2, т.е. количество товаров в заказах всех клиентов.

Вычисления и итоговые функции можно комбинировать разными способами. Например, чтобы получить список со стоимостью всех товаров в каждом заказе, нужно определить стоимость товара (эти сведения хранятся в таблице tblInventory) в каждом заказе и умножить ее на количество этих товаров в заказе (эти сведения хранятся в таблице tblOrderItem), а затем сложить полученные произведения в каждом заказе.

SELECT tblOrderItem.OrderID, SUM(Quantity * Price)
tblOrderItem ON tblItem.ID = tblOrderItem.OrderID GROUP BY OrderID

Этот запрос возвращает приведенный ниже результирующий набор.

OrderID OrderTotal
1 15.64
2 7.98
3 5.99
4 99.17
5 13.96
6 49.07
7 55.88
8 13.97
9 9.16
10 14.76

Запросы на объединение

Запрос на объединение (union query) выполняет объединение содержимого двух таблиц, имеющих одинаковые структуры полей. Это оказывается полезным, когда нужно отобразить в одном результирующем наборе потенциально не связанные записи из нескольких источников.

Далее в главе приводятся примеры сохранения старых заказов в архивной таблице с именем tblOrderArchive. И если вы воспользуетесь предложенной системой архивирования, то записи физически будут размещены в двух отдельных таблицах. Это может повысить эффективность работы: запрос выполняется быстрее на маленькой таблице, чем на большой. Но, возможно, в некоторых случаях понадобится просмотреть все текущие и заархивированные записи в одном общем результирующем наборе. С такой задачей прекрасно справится запрос на объединение.

Предположим, что как раз возникла необходимость в просмотре в одном результирующем наборе старых записей из таблицы tblOrderArchive и новых записей из tblOrder. Такой запрос приведен ниже.

После выполнения этого запроса старые и новые заказы объединятся в одном результирующем наборе, причем результат будет выглядеть подобно исходной таблице до архивирования.

По умолчанию запрос на объединение не возвращает записи-дубликаты (хотя было бы неплохо, чтобы ваша система архивирования записей не удаляла их после копирования в таблицу архива). Отображение записей-дубликатов может оказаться весьма полезным, если система архивирования старых записей не удаляет записи после копирования в архивную таблицу и вам нужно просмотреть и сравнить некоторые старые и новые записи.

Однако, добавив ключевое слово ALL, можно заставить запрос на объединение отображать дублирующие записи, как показано ниже.

Подзапросы

Подзапрос (subquery) - это запрос, результат которого служит критерием для другого запроса. Подзапросы занимают место обычного выражения WHERE. Поскольку результат, сгенерированный подзапросом, используется вместо выражения, подзапрос может возвращать только одиночное значение (в противоположность обычному запросу, который возвращает несколько значений, представленных в виде строк и столбцов).

Единственное синтаксическое различие между подзапросом и выражением любого другого типа, размещенным в предложении WHERE, состоит в том, что подзапрос должен быть заключен в круглые скобки. Например, нужно создать запрос, который отображает заказы с самыми дорогими товарами. Дорогим считается такой товар, стоимость которого превышает среднюю стоимость товаров в таблице tblItem. Поскольку среднюю стоимость товара легко определить (выполнив итоговую функцию AVG по полю UnitPrice в таблице tblItem), это значение можно использовать как подзапрос в более крупном запросе. Такой запрос SQL приведен ниже.

WHERE (UnitPrice > (SELECT AVG(UnitPrice) FROM tblItem)

В этом случае оказывается, что запрос и подзапрос обращаются к одной и той же таблице, но это не принципиально. Подзапросы могут делать запросы к любой таблице в базе данных, главное – чтобы они возвращали одиночное значение.

Приведенная выше инструкция 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 могут пре

доставить полезную информацию (например, правильную строку подключения для соединения с базой данных) или генерировать в окне конструктора основные DML-команды при извлечении данных из таблицы или изменении типа запроса.

НА ЗАМЕТКУ

Примеры в этом разделе демонстрируют способы изменения данных в базе данных Novelty. Если после многочисленных попыток изменить данные вы хотите вернуть базу данных Noveltу в ее прежнее состояние, то ее можно переустановить, запуская описанный во введении к этой книге сценарий.

На низком уровне (т.е. не на уровне графического интерфейса пользователя) 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, ограничивающий число записей, на которые воздействует запрос на обновление.

Например, чтобы увеличить цену на все товары, воспользуйтесь запросом на обновление, код которого приведен ниже.

Команда SELECT, которая располагается вслед за предложением UPDATE, не обязательна и предназначена для просмотра результатов обновления.

Ниже приведены значения полей после выполнения данного запроса на обновление.

ID Name Description UnitPrice Price
1 Rubber Chicken A classic laugh getter 2.0300 6.5890
2 Hand Buzzer Shock your friends .8600 1.5290
3 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

Для ограничения числа записей, подвергаемых воздействию запроса на обновление, достаточно добавить в запрос SQL предложение WHERE. Например, чтобы применить повышение цен только к дорогим товарам, стоимость которых больше $100, откорректируйте запрос так, как показано ниже.

Эта команда увеличивает на 10% цену на товары, текущая цена которых больше $100.

Запросы на удаление

С помощью запроса на удаление (delete query) можно одним махом удалить одну или несколько записей. Например, чтобы удалить все заказы, которые были оформлены до (но не во время) последнего празднования Дня всех святых, воспользуйтесь запросом SQL, код которого приведен ниже.

WHERE OrderDate < "10/31/2002"

Запрос на добавление записей

Запрос на добавление (append query) используется в двух случаях:

При добавлении одиночной записи в таблицу;

При копировании одной или нескольких записей из одной таблицы в другую.

Для создания запроса на добавление используйте предложение SQL INSERT. Точный синтаксис запроса зависит от того, добавляете ли вы одну запись или копируете несколько. Например, для добавления одной новой записи в tblOrder можно использовать приведенный ниже запрос.

INSERT INTO tblOrder(CustomerID, OrderDate)

При выполнении этого запроса в таблице tblOrder создается новый заказ для клиента с идентификационным номером 119 и датой 16 июня 2001 года.

НА ЗАМЕТКУ

В этом запросе на добавление для поля ID таблицы tblOrder не предлагается никакого значения, так как это поле идентификации. Попытка пользователя присвоить значение этому полю приведет к возникновению ошибки, поскольку его может сгенерировать только сам процессор баз данных.

Для создания разновидности запроса на добавление, который копирует записи из одной таблицы в другую, используйте предложение INSERT вместе с предложением SELECT. Предположим, вместо удаления старых заказов вы архивируете их, периодически копируя в архивную таблицу tblOrderArchive, которая имеет ту же структуру, что и tblOrder. Для выполнения этой работы необходимо сначала создать таблицу tblOrderArchive со структурой, аналогичной tblOrder.

НА ЗАМЕТКУ

Как уже сообщалось выше, команды SQL для создания и управления структурой базы данных называются командами манипулирования данными или DML-командами. Более подробно они рассматриваются далее в главе.

Ниже приведена инструкция SQL для копирования старых записей из tblOrder в tblOrderArchive.

При выполнении этой инструкции SQL в таблицу tblOrderArchive копируются все записи, содержащие заказы, которые были оформлены до 1 июня 2001 года.

Запросы на основе команды SELECT INTO

Запрос на основе команды SELECT INTO аналогичен запросу на добавление, за исключением того, что он создает новую таблицу и сразу же копирует в нее записи. В Microsoft Access он называется запросом на создание таблиц (make-table query). Так, в предыдущем примере все записи из таблицы tblOrder копировались в таблицу tblOrderArchive, исходя из предположения, что таблица tblOrderArchive уже существует. Вместо этого запроса для копирования тех же записей в новую таблицу с такой же структурой, как и у оригинала, воспользуйтесь приведенным ниже запросом SQL.

НА ЗАМЕТКУ

Этот запрос копирует все записи из tblOrder в новую таблицу с именем tblOrderArchive. Однако если такая таблица уже существует, эта команда не будет выполнена. Это отличается от результата выполнения данного запроса в Microsoft Access.

Если его выполнить в окне конструктора запросов программы Access при условии, что таблица tblOrderArchive уже существует, то процессор баз данных удалит исходную таблицу и заменит ее вновь созданной, которая будет заполнена содержимым скопированных записей. В 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.

Тип данных char(2), означает, что процессор баз данных должен создать текстовое поле фиксированной длины для хранения максимум двух символов, а выражение varchar (50) указывает на создание поля с переменной длиной до 50 символов.

При выполнении этого запроса будет создана таблица со следующей структурой:

tblRegion
State
Region

В разделе о типах данных главы 1, "Основы построения баз данных", перечислены допустимые типы данных полей, которые можно использовать при создании полей.

Добавление ограничений в таблицу

В процессе создания таблицы можно добавить ограничения (constraints). Они аналогичны индексу, но используются для обозначения уникального, первичного или внешнего ключа.

Ограничение создается с помощью предложения SQL CONSTRAINT, которое принимает два параметра: имя индекса и имя поля или полей, в индексации которых вы заинтересованы. Можно объявить индекс с помощью ключевого слова UNIQUE или PRIMARY, и тогда этот индекс будет означать, что поле может принимать только уникальные значения или что поле (поля) служит первичным ключом таблицы.

НА ЗАМЕТКУ

Понятие именованных индексов может показаться несколько странным для тех, кто привык работать в Microsoft Access, поскольку Access скрывает имена индексов в своем пользовательском интерфейсе. Однако к имени индекса можно получить доступ программным путем.

Например, усовершенствовать таблицу tblRegion, созданную в предыдущем примере, можно добавлением уникального индекса к полю State, поскольку оно используется в объединении. Ниже представлена команда SQL, создающая эту таблицу с использованием предложения CONSTRAINT.

CONSTRAINT StateIndex UNIQUE (State)

Этот запрос создает таблицу с уникальным индексом по полю State, причем этот индекс имеет имя StateIndex.

Несмотря на то что в приведенном выше примере индексируется поле State, больше смысла было бы в том, чтобы сделать поле State первичным ключом таблицы. В этом случае вы получили бы гарантию того, что в поле State не было не только повторяющихся значений, но и значений NULL. Ниже приводится команда SQL, создающая таблицу tblRegionNew, в которой первичным ключом является поле State.

State char Region varchar (50),
CONSTRAINT StatePrimary PRIMARY KEY (State)

Назначение внешнего ключа

Для того чтобы назначить поле в качестве внешнего ключа, используйте ограничение FOREIGN KEY. Например, в структуре нашей базы данных существует отношение типа один-ко-многим между полем State таблицы tblRegion и соответствующим полем State таблицы tblCustomer. Команда SQL, используемая для создания таблицы tblCustomer, может выглядеть так, как показано ниже.

CONSTRAINT IDPrimary PRIMARY KEY (ID),
CONSTRAINT StateForeign FOREIGN KEY (State)
REFERENCES tblRegionNew (State)

Обратите внимание, что внешний ключ в команде CREATE TABLE не создает индекс по этому внешнему ключу. Он только служит для создания отношения между двумя таблицами.

Создание индексов с помощью команды CREATE INDEX

Помимо создания индексов в процессе формирования таблицы (с помощью предложения CONSTRAINT), можно также создавать индексы уже после того, как таблица сформирована (с помощью предложения CREATE INDEX). Это полезно в тех случаях, когда таблица уже существует (в то время как предложение CONSTRAINT применяется для формирования индексов только в момент создания таблицы).

Для создания индекса в существующей таблице используйте приведенную ниже команду SQL.

Для того чтобы создать уникальный индекс, используйте ключевое слово UNIQUE, как показано ниже.

CREATE UNIQUE INDEX StateIndex

Чтобы создать первичный индекс в существующей таблице, используйте приведенную ниже команду SQL.

CREATE UNIQUE NONCLUSTERED INDEX StateIndex ON tblRegion (

Удаление таблиц и индексов с помощью предложения DROP

Удалять элементы базы данных можно с помощью предложения DROP. Например, чтобы удалить таблицу, используйте приведенную ниже команду SQL.

С помощью предложения DROP можно также удалить индекс в таблице, как показано ниже.

DROP INDEX tblRegion.StateIndex

Обратите внимание, что для удаления первичного ключа нужно знать имя этого ключа.

У вас также есть возможность удалять отдельные поля таблиц. Для этого нужно использовать предложение DROP внутри предложения ALTER TABLE, как показано в следующем разделе. А для удаления базы данных применяется команда DROP DATABASE.

Модификация структуры таблицы с помощью предложения ALTER

С помощью предложения ALTER можно изменить определения полей в таблице. Например, чтобы добавить поле CustomerType в tblCustomer, используйте приведенную ниже команду SQL.

Для того чтобы удалить поле из базы данных, используйте предложение DROP COLUMN вместе с предложением ALTER TABLE, как показано ниже.

Кроме того, с помощью предложения ALTER TABLE можно добавить в таблицу ограничения. Например, для создания отношения между таблицами tblCustomer и tblOrder с помощью предложения ALTER TABLE используйте приведенную ниже команду SQL.

ADD CONSTRAINT OrderForeignKey

Помните, что добавление ограничения не создает обычного индекса по полю, оно просто делает поле уникальным, назначает поле первичным ключом или создает отношение между двумя таблицами.

Резюме

Эта глава посвящена технологии создания запросов, которые могут использоваться в приложениях доступа к базам данных, созданных в среде Visual Basic .NET. Здесь рассматривались запросы, которые возвращают необходимые записи, а также запросы, которые создают и модифицируют структуру баз данных.

Большая часть материала этой главы приводится отнюдь не ради увеличения объема книги; начав программировать с использованием Visual Studio .NET и ADO.NET, вы почувствуете реальную пользу от прочитанного.

Вопросы и ответы

Почему имена таблиц и полей иногда заключены в квадратные скобки?

Квадратные скобки часто окружают имена объектов в среде Visual Studio.NET и административных инструментах SQL Server для исключения проблем при использовании имен с пробелами и другими зарезервированными символами и словами. Например в базе данных Northwind, которая инсталлируется вместе с SQL Server 2000, есть таблица с именем Order Details. Хотя в общем случае не рекомендуется включать пробелы в имена таблиц, ее все же можно использовать в SQL Server в виде . Однако инструменты с графическим интерфейсом, например в среде Visual Studio .NET, всегда добавляют квадратные скобки. Но в данной книге они не используются, чтобы исключить излишнюю работу по их вводу.

Почему перед именем таблицы иногда используется приставка dbo? Что это такое?

dbo - это вспомогательный квалификатор (или моникер), который используется в инструментах с графическим интерфейсом при работе с SQL Server. Он позволяет установить соединение заданного объекта базы данных с владельцем базы данных. Объекты базы данных могут иметь разных владельцев, a dbo представляет собой сокращенную форму записи следующего высказывания: "этот объект относится к владельцу используемой базы данных". Разные объекты одной базы данных вполне могут относиться к разным владельцам, хотя, конечно, следует признать, что такая ситуация встречается редко. В базах данных, в которых все объекты относятся к владельцу dbo, этот моникер можно опустить (однако инструменты с графическим интерфейсом все равно попытаются вставить его).

В этом приложении содержатся сокращённые описания различных команд SQL. Цель состоит в том, чтобы дать вам быструю и точную справку и определение SQL.

Первый раздел этого приложения определяет элементы, используемые для создания команд SQL; второй - подробности синтаксиса и предложения с кратким описанием самих команд.

Вот стандартные условные обозначения (они называются BNF-условиями):

  • Ключевые слова набираются в верхнем регистре.
  • SQL и другие специальные условия заключаются в угловые скобки и набираются курсивом.(<и >)
  • Необязательные части команд находятся в квадратных скобках ([ и ]).
  • Многоточие (....) указывает на то, что предшествующая часть команды может повторяться любое число раз.
  • Вертикальная полоса (|) означает: то, что ей предшествует, может быть заменено на то, что следует за ней.
  • Фигурные Скобки ({ и }) указывают: всё, что внутри них, должно быть расценено как целое, для оценки других символов (например, вертикальных полос или эллипсов).
  • Двойное двоеточие и знак равенства (:: =) означают: то, что следует за ними, является определением того, что им предшествует.

    Кроме того, мы будем использовать следующую последовательность (.,..) чтобы указывать, что предшествующее этому может повторяться любое число раз, с индивидуальными событиями, отделяемыми запятыми. Атрибуты, которые не являются частью официального стандарта, будут отмечены в описании как (*нестандартные*).

    ОБРАТИТЕ ВНИМАНИЕ: Терминология которую мы используем здесь - не является официальной терминологией ANSI. Официальная терминология может вас сильно запутать, поэтому мы несколько ее упростили.
    По этой причине мы иногда используем условия, отличающиеся от ANSI, или используем те же самые условия, но несколько по-иному. Например, наше определение Отличается от используемой в ANSI комбинации стандартного определения С .

    ЭЛЕМЕНТЫ SQL

    Этот раздел определяет элементы команд SQL.

    Они разделены на две категории: Основные элементы языка и Функциональные элементы языка .

    Основные элементы - это создаваемые блоки языка; когда SQL исследует команду, то он сначала оценивает каждый символ в тексте команды в терминах этих элементов. Разделитель отделяет одну часть команды от другой; всё, что находится между разделителями , обрабатывается как модуль. Основываясь на этом разделении, SQL интерпретирует команду.

    Функциональные элементы - это разнообразные элементы, отличающиеся от ключевых слов, которые могут интерпретироваться как модули. Это части команды, отделяемые с помощью разделителей , имеющие специальное значение в SQL. Некоторые из них являются специальными для определенных команд и будут описаны вместе с этими командами позже в этом приложении.

    Перечисленные здесь являются общими элементами для всех описываемых команд.

    Функциональные элементы могут определяться в терминах друг друга или даже в собственных терминах. Например, предикат Наш последний и наиболее сложный случай, содержит предикат Внутри собственного определения. Это потому, что предикат Использующий AND или OR, может содержать любое число предикатов Которые могут работать автономно. Мы представляли вам предикат В отдельной секции в этом приложении из-за разнообразия и сложности этого функционального элемента языка. Он будет постоянно присутствовать при обсуждении других функциональных частей команд.

    БАЗОВЫЕ ЭЛЕМЕНТЫ ЯЗЫКА

    ЭЛЕМЕНТ ОПРЕДЕЛЕНИЕ | | -- пробел определяемый реализацией конец символьной строки [{ | не должен быть длиннее 18-ти символов. ЭЛЕМЕНТ ОПРЕДЕЛЕНИЕ - % любое из следующих: , () <> . : = + " - | <> >= <= или [любой печатаемый текст в одинарных кавычках] Примечание: В , две последовательных одинарных кавычки (" ") интерпретируются как одна ("). окончание/терминатор, зависящее от главного языка. (*только вложенный SQL*)

    ФУНКЦИОНАЛЬНЫЕ ЭЛЕМЕНТЫ

    Следующая таблица показывает функциональные элементы команд SQL и их определения: ЭЛЕМЕНТ ОПРЕДЕЛЕНИЕ Предложение SELECT Заключённое в круглые скобки предложение SELECT внутри другого условия, которое фактически оценивается отдельно для каждой строки-кандидата другого предложения. | | любое из следующих: + - / * | | | | | ЭЛЕМЕНТ ОПРЕДЕЛЕНИЕ USER | [
    | .] | | NOT NULL | UNIQUE | CHECK () | PRIMARY KEY | REFERENCES
    [()] UNIQUE () | CHECK () | PRIMARY KEY () | FOREIGN KEY () | REFERENCES
    [()] ЗНАЧЕНИЕ ПО УМОЛЧАНИЮ = Допустимый тип данных (См. в Приложении B описание типов, обеспечиваемых ANSI, или в Приложении C - другие общие типы.) Значение зависит от (См. Приложение B .) (*нестандартный*) .,.. .,..
    {
    [] } .,..

    ПРЕДИКАТЫ

    Здесь определён список различных типов предиката Описанных на следующих страницах:

    ::=

    { | | | | | | } BETWEEN
    AND

    - A BETWEEN B AND C имеет такое же значение, что и - (A>= B AND <= C). , для которого A NOT BETWEEN B AND C, имеет такое же значение, что и NOT (BETWEEN B AND C).
    может быть выведено с помощью нестандартного запроса (*nonstandard*).

    Синтаксис

    IN |

    Список значений будет состоять из одного или более значений в круглых скобках с разделением запятыми, которые имеют сравнимый с тип данных. Если используется подзапрос , он должен содержать только одно выражение в предложении SELECT (возможно и больше, но это уже будет вне стандарта ANSI).
    Подзапрос фактически выполняется отдельно для каждой строки-кандидата основного запроса, и значения, которые он выведет, будут составлять список значений для этой строки. В любом случае предикат будет верен, если выражение представленное в списке значений , если не указан NOT.
    Фраза A NOT IN (B, C) является эквивалентом фразы NOT (A IN (B, C)).

    Синтаксис

    LIKE

    это любое *нестандартное* выражение алфавитно-цифрового типа.
    может быть, в соответствии со стандартом, только определенным столбцом . Образец Состоит из строки, которая будет проверена на совпадение с . Символ окончания это одиночный алфавитно-цифровой символ. Совпадение произойдет, если верны следующие условия:

  • Для каждого символа подчёркивания в образце Который не предшествует символу окончания , имеется один соответствующий ему символ .
  • Для каждого В образце Который не предшествует , имеются нуль или более соответствующих символов в .
  • Для каждого в Который не предшествует другому , нет никакого соответствующего символа в .
  • Для каждого иного символа в Один и тот же символ устанавливается у соответствующей отметке в .

    Если совпадение произошло, верен, если не был указан NOT. Фраза NOT LIKE "текст" - эквивалентна NOT (A LIKE "текст").

    Синтаксис

    IS NULL

    = IS NULL, если NULL значение представлено в этом столбце. Это сделает верным, если не указан NULL. Фраза IS NOT NULL, имеет тот же результат что и NOT ( IS NULL).

    Синтаксис



    :: = ANY | ALL | SOME

    Предложение SELECT подзапроса должно содержать одно, и только одно, выражение значения . Все значения, выведенные подзапросом , составляют набор результатов . сравнивается, используя оператор связи , с каждым членом набора результатов . Это сравнение оценивается следующим образом:

  • Если = ALL и каждый член набора результатов делает это сравнение верным, верен.
  • Если = ANY и имеется по крайней мере один член из набора результатов , который делает верным это сравнение, то является верным.
  • Если набор результатов пуст, то верен, если = ALL , и неверен а ином случае.
  • Если = SOME, эффект - тот же, что и для ANY.
  • Если неверен и не неверен, он неизвестен.

    Синтаксис:

    EXISTS ()

    Если подзапрос выводит одну или более строк вывода, верен; и неверен в ином случае.

    SQL КОМАНДЫ

    Этот раздел подробно описывает синтаксис различных команд SQL. Это даст вам возможность быстро отыскивать команду, находить синтаксис и краткое описание её работы.

    ИМЕЙТЕ ВВИДУ: команды, которые начинаются словами - EXEC SQL, а также команды или предложения, заканчивающиеся словом, могут использоваться только во вложенном SQL.

    BEGIN DECLARE SECTION (НАЧАТЬ РАЗДЕЛ ОБЪЯВЛЕНИЙ)

    Синтаксис

    EXEC SQL BEGIN DECLARE SECTION EXEC SQL END DECLARE SECTION

    Эта команда создает главный раздел программы для объявления в ней главных переменных, которые будут использоваться во вкладываемых операторах SQL. Переменная SQLCODE должна быть включена как одна из объявляемых переменных главного языка.

    CLOSE CURSOR (ЗАКРЫТЬ КУРСОР)

    Синтаксис

    EXEC SQL CLOSE CURSOR ;

    Эта команда указывает курсору закрыться, после чего ни одно значение не сможет быть выбрано из него до тех пор, пока он не будет снова открыт.

    COMMIT (WORK) (ПОДТВЕРДИТЬ (ТРАНЗАКЦИИ))

    Синтаксис

    Эта команда оставляет неизменными все изменения, сделанных в базе данных, до тех пор, пока начавшаяся транзакция не закончится и не начнется новая транзакция.

    CREATE INDEX (СОЗДАТЬ ИНДЕКС)

    (*NONSTANDARD*) (НЕСТАНДАРТНАЯ)

    Синтаксис

    CREATE INDEX
    ON

  • ();

    Эта команда создает эффективный маршрут с быстрым доступом для поиска строк, содержащих указанные столбцы. Если UNIQUE указана, таблица не сможет содержать дубликаты (двойники) значений в этих столбцах.

    CREATE SYNONYM (*NONSTANDARD*)
    (СОЗДАТЬ СИНОНИМ) (*НЕСТАНДАРТНЫЙ*)

    Синтаксис

    CREATE IPUBLICl SYNONYM FOR
    .

    ;

    Эта команда создает альтернативное (синоним) имя таблицы. Синоним принадлежит его создателю, а сама таблица - обычно другому пользователю. Используя синоним, его владелец может не ссылаться на таблицу её полным (с включением имени владельца) именем. Если PUBLIC указан, синоним принадлежит каталогу SYSTEM и, следовательно, доступен всем пользователям.

    CREATE TABLE (СОЗДАТЬ ТАБЛИЦУ)

    Синтаксис

    CREATE TABLE


    ({ []
    [ . . .]
    []} . , . . . , . .);

    Команда создает таблицу в базе данных. Эта таблица будет принадлежать её создателю. Столбцы будут рассматриваться в поимённом порядке.
    определяет тип данных, которые столбец будет содержать. Стандарт описывается в Приложении B ; все прочие используемые типы данных обсуждались в Приложении C . Значение размера зависит от типа данных .
    и налагают ограничения на значения, которые могут быть введены в столбце.
    определяет значение (по умолчанию), которое будет вставлено автоматически, если никакого другого значения не указано для этой строки. (См. в Главе 17 подробности о самой команде CREATE TABLE и в Главах И - подробности об ограничениях и о ).

    CREATE VIEW (СОЗДАТЬ ПРОСМОТР)

    Синтаксис

    CREATE VIEW


    AS
    ;

    Просмотр обрабатывается как любая таблица в командах SQL. Когда команда ссылается на имя таблицы

    , запрос выполняется, и его вывод соответствует содержанию таблицы, указанной в этой команде.
    Некоторые просмотры могут модифицироваться, что означает, что команды модификации могут выполняться в этих просмотрах и передаваться в таблицу, на которую была ссылка в запросе . Если указано предложение WITH CHECK OPTION, эта модификация должны также удовлетворять условию предиката В запросе .

    DECLARE CURSOR (ОБЪЯВИТЬ КУРСОР)

    Синтаксис

    EXEC SQL DECLARE CURSOR FOR

    Эта команда связывает имя курсора с запросом . Когда курсор открыт (см. OPEN CURSOR), запрос выполняется, и его результат может быть выбран (командой FETCH) для вывода. Если курсор - модифицируемый, таблица, на которую ссылается запрос , может получить изменение содержания с помощью операции модификации в курсоре (См. в Главе 25 о модифицируемых курсорах).

    DELETE (УДАЛИТЬ)

    Синтаксис

    DELETE FROM


    { ; }
    | WHERE CURRENT OF

    Если предложение WHERE отсутствует, ВСЕ строки таблицы удаляются. Если предложение WHERE использует предикат Строки, которые удовлетворяют условию этого предиката Удаляются. Если предложение WHERE имеет аргумент CURRENT OF (ТЕКУЩИЙ) в имени курсора , строка из таблицы

    , на которую в данный момент имеется ссылка с помощью имени курсора , будет удалена. Форма WHERE CURRENT может использоваться только во вложенном SQL и только с модифицируемыми курсорами.

    EXEC SQL (ВЫПОЛНИТЬ SQL)

    Синтаксис

    EXEC SQL

    EXEC SQL используется, чтобы указывать начало всех команд SQL, вложенных в другой язык.

    FETCH (ВЫБОРКА/ИЗВЛЕЧЕНИЕ)

    Синтаксис

    EXEC SQL FETCH
    INTO

    FETCH принимает вывод из текущей строки запроса , вставляет её в список главных переменных , и перемещает курсор на следующую строку. Список может включать переменную indicator в качестве целевой переменной (См. Главу 25).

    GRANT (ПЕРЕДАТЬ ПРАВА)

    Синтаксис (стандартный)

    GRANT ALL
    | {SELECT
    | INSERT
    | DELETE
    | UPDATE [()]
    | REFERENCES [()l } . , . .
    ON

    . , . .
    TO PUBLIC | . , . .
    ;

    Аргумент ALL (ВСЕ), с или без PRIVILEGES (ПРИВИЛЕГИИ), включает каждую привилегию в список привилегий. PUBLIC (ОБЩИЙ) включает всех существующих пользователей и всех созданных в будущем. Эта команда даёт возможность передать права для выполнения действий в таблице с указанным именем. REFERENCES позволяет дать права на использование столбцов в списке столбцов как родительский ключ для внешнего ключа. Другие привилегии состоят из права выполнять команды, для которых привилегии указаны их именами в таблице. UPDATE подобен REFERENCES и может накладывать ограничения на определенные столбцы. GRANT OPTION даёт возможность передавать эти привилегии другим пользователям.

    Синтаксис (нестандартный)

    GRANT DBA
    | RESOURCE
    | CONNECT ... .
    TO . , . .
    | . , . . }
    FROM { PUBLIC
    | . , . . };

    Привилегия Может быть любой из указанных в команде GRANT. Пользователь, дающий REVOKE, должен иметь те же привилегии, что и пользователь, который давал GRANT. Предложение ON может быть использовано, если применяется привилегия специального типа для особого объекта.

    ROLLBACK (WORK)
    (ОТКАТ) (ТРАНЗАКЦИИ)

    Синтаксис

    Команда отменяет все изменения в базе данных, сделанные в течение текущей транзакции. Она, кроме того, заканчивается текущую и начинает новую транзакцию.

    SELECT (ВЫБОР)

    Синтаксис

    SELECT { IDISTINCT | ALL] . , . . } / *
    FROM

    . , . .

    . , . . ];

    Это предложение организует запрос и выводит значения из базы данных (см. Главы 3 - 14).

    Применяются следующие правила:

  • Если ни ALL, ни DISTINCT не указаны, принимается ALL.
  • Выражение состоит из , агрегатной функции , нестандартной функции , постоянной или любой их комбинации с операторами в допустимых выражениях.
  • Таблица, на которую ссылаются,
  • , состоит из имени таблицы, включая префикс владельца, если текущий пользователь не владелец, или синоним (нестандартно) таблицы. Таблица может быть или базовой таблицей, или просмотром. В принципе псевдоним может указать, какой синонимом используется для таблицы, только на время текущей команды. Имя таблицы или синоним должны отделяться от псевдонима одним или более разделителями .
  • Если используется GROUP BY, все столбцы , используемые в предложении SELECT, должны будут использоваться как группа столбцов , если они не содержатся в агрегатной функции . Вся группа столбцов должна быть представлена среди выражений , указанных в предложении SELECT. Для каждой отдельной комбинации значений группы столбцов будет иметься одна, и только одна, строка вывода.
  • Если HAVING используется, предикат Применяется к каждой строке, произведённой предложением GROUP BY, и те строки, которые сделают этот предикат верным, будут выведены.
  • Если ORDER BY используется, вывод имеет определенную последовательность. Каждый идентификатор столбца ссылается на указанное в предложении SELECT. Если это является указанным столбцом , может быть таким же, как . Иначе может быть положительным целым числом, указывающим место, где находится в последовательности предложения SELECT. Вывод будет сформирован так, чтобы помещать значения, содержащиеся в , в порядке возрастания, если DESC не указан. Имя идентификатора столбца , стоящее первым в предложении ORDER BY, будет предшествовать позже стоящим именам в определении последовательности вывода.

    Предложение SELECT оценивает каждую строку-кандидат таблицы, в которой строки показаны независимо.

    Строка-кандидат определяется следующим образом:

  • Если только одна ссылаемая таблица
  • включена, каждая строка этой таблица в свою очередь является строкой-кандидатом.
  • Если более одной ссылаемой таблицы
  • включено, каждая строка каждой таблицы должна быть скомбинирована, в свою очередь, с каждой комбинацией строк из всех других таблиц. Каждая такая комбинация будет, в свою очередь, строкой-кандидатом.

    Каждая строка-кандидат производит значения, которые делают предикат В предложении WHERE верным, неверным, или неизвестным. Если GROUP BY не используется, каждое применяется, в свою очередь, для каждой строки-кандидата, чьё значение делает предикат верным, и результатом этой операции является вывод.
    Если GROUP BY используется, строки-кандидаты комбинируются, используя агрегатные функции. Если никакого предиката Не установлено, каждое выражение применяется к каждой строке-кандидату или к каждой группе. Если указан DISTINCT, дубликаты (двойники) строк будут удалены из вывода.

    UNION (ОБЪЕДИНЕНИЕ)

    Синтаксис

    {UNION } . . . ;

    Вывод двух или более запросов будет объединён. Каждый запрос должен содержать один и тот же номер в предложении SELECT и в таком порядке, что 1.. n каждого совместим по типу данных и размеру с 1.. n всех других.

    UPDATE (МОДИФИКАЦИЯ)

    Синтаксис

    UPDATE


    SET { = } . , . .
    {[ WHERE ]; }
    | {
    ]}

    UPDATE изменяет значения в каждом столбце на соответствующее значение . Если предложение WHERE использует предикат То только строки таблиц, чьи текущие значения делают этот предикат Верным, могут быть изменены. Если WHERE использует предложение CURRENT OF, то значения в строке таблицы

    , находящиеся в курсоре , меняются. WHERE CURRENT OF пригодно для использования только во вложенном SQL, и только с модифицируемыми курсорами. При отсутствии предложения WHERE, все строки меняются.

    WHENEVER (ВСЯКИЙ РАЗ КАК)

    Синтаксис

    EXEC SQL WHENEVER
    :: = SQLERROR | NOT FOUND | SQLWARNING
    (последнее - нестандартное)
    :: = CONTINUE | GOTO | GOTO
    :: = зависит от главного языка

    Любая концептуальная информация о реляционных базах данных и таблицах приносит пользу лишь в том случае, если вы знаете, как организовать взаимодействие с данными. Язык SQL состоит из структурированных команд, предназначенных для добавления, модификации и удаления данных из базы. Эти команды образуют основу для взаимодействия с сервером PostgreSQL.

    Этот раздел посвящен "анатомии" команд SQL. В нем рассматриваются структурные компоненты команд, описываются функции каждого компонента и их взаимные связи. Стандартный клиент командной строки PostgreSQL, psql, выводит результаты выполнения команд в приведенных примерах.

    Большинство примеров команд SQL относится к базе данных booktown . Весь вывод psql снабжается префиксом вида booktown=# .

    В некоторых примерах используется тестовая база данных testdb . По умолчанию в приглашении psql выводится только имя базы данных и символы =# , означающие, что система готова к вводу новой команды (хотя вы увидите, что символ = динамически изменяется по мере отслеживания состояния входных данных SQL). В книге это приглашение приводится вместе с входными и выходными данными SQL, чтобы вам было проще освоиться с выводом клиента psql.

    Клиент psql подробно описан в главе 4. Здесь он упоминается лишь для пояснения стиля примеров команд SQL.

    Примечание
    Схема базы данных booktown (вместе с примерами записей) находится в файле booktown.sql на компакт-диске. Чтобы установить эту базу данных, введите в приглашении командной строки команду psql - U postgres template! - f /mnt/cdrom/booktown.sql, где /mnt/cdrom - путь к смонтированному компакт-диску, a postgres - имя суперпользователя PostgreSQL
    .

    Анатомия команд SQL

    Команды SQL всегда начинаются с действия (verb ) - слова или группы слов, описывающих выполняемую операцию. Кроме того, команда SQL обычно содержит одну или несколько секций, уточняющих ее смысл. В табл. 3.2 перечислены основные действия SQL.

    Таблица 3.2 . Основные действия PostgreSQL.

    Действие Описание
    CREATE DATABASE Создание новой базы данных
    CREATE INDEX Создание нового индекса для столбца таблицы
    CREATE SEQUENCE Создание новой последовательности в существующей базе данных
    CREATE TABLE Создание новой таблицы в существующей базе данных
    CREATE TRIGGER Создание нового определения триггера
    CREATE VIEW Создание нового представления для существующей таблицы
    SELECT Выборка записей из таблицы
    INSERT Вставка одной или нескольких новых записей в таблицу
    UPDATE Модификация данных в существующих записях
    DELETE Удаление существующих записей из таблицы
    DROP DATABASE Уничтожение существующей базы данных
    DROP INDEX Удаление индекса столбца из существующей таблицы
    DROP SEQUENCE Уничтожение существующего генератора последовательности
    DROP TABLE Уничтожение существующей таблицы
    DROP TRIGGER Уничтожение существующего определения триггера
    DROP VIEW Уничтожение существующего представления
    CREATE USER Создание в системе новой учетной записи пользователя PostgreSQL
    ALTER USER Модификация существующей учетной записи пользователя PostgreSQL
    DROP USER Удаление существующей учетной записи пользователя PostgreSQL
    GRANT Предоставление прав доступа к объекту базы данных
    REVOKE Лишение прав доступа к объекту базы данных
    CREATE FUNCTION Создание новой функции SQL в базе данных
    CREATE LANGUAGE Создание нового определения языка в базе данных
    CREATE OPERATOR Создание нового оператора SQL в базе данных
    CREATE TYPE Создание нового типа данных SQL в базе данных
    ITunes