Московский государственный университет имени М.В.Ломоносова
Опубликован: 10.10.2005 | Доступ: свободный | Студентов: 8464 / 634 | Оценка: 3.85 / 3.50 | Длительность: 22:03:00
Лекция 3:

Общая характеристика оператора SELECT и организация списка ссылок на таблицы в разделе FROM

< Лекция 2 || Лекция 3: 12345 || Лекция 4 >

Общая структура оператора выборки в языке SQL

Для выборки данных в прямом SQL используется оператор SELECT, возвращающий набор4Мы сознательно используем здесь термин набор, поскольку в обоих случаях результатом выполнения оператора выборки не является таблица. из одной или нескольких строк одинаковой структуры и задаваемый в следующем синтаксисе:

SELECT [ ALL | DISTINCT ] select_item_commalist
	FROM table_reference_commalist
	  [ WHERE conditional_expression ]
	    [ GROUP BY column_name_commalist ]
	      [ HAVING conditional_expression ] 
	        [ ORDER BY order_item_commalist ]

Семантика оператора выборки

Для начала опишем общую схему выполнения оператора SELECT в соответствии с предписаниями стандарта5Не следует понимать эту схему таким образом, что запросы к SQL-ориентированной базе данных действительно должны выполняться именно таким образом. Более того, ни одна реализация SQL не придерживается в точности этой схеме. Но как бы реально не выполнялся оператор выборки, результат должен быть таким же, как если бы он получался при точном следовании описываемой схеме выполнения. Выполнение запроса состоит из нескольких шагов, соответствующих разделам оператора выборки. На первом шаге выполняется раздел FROM. Если список ссылок на таблицы ( table_reference_commalist ) этого раздела соответствует таблицам A, B, … C 6 A, B и C не обязаны являться базовыми таблицами. См. следующий подраздел., то в результате выполнения раздела FROM образуется таблица (назовем ее T ), являющаяся расширенным декартовым произведением таблиц A, B, …, C. Если в разделе FROM указана только одна таблица, то она же и является результатом выполнения этого раздела. Как говорилось в лекции 3, в реляционной алгебре для корректного выполнения операции взятия расширенного декартова произведения отношений в общем случае требуется применение операции переименования атрибутов. Соответствующие возможности переименования столбцов таблиц, указанных в списке раздела FROM, поддерживаются и в SQL. Альтернативный способ именования столбцов результирующей таблицы T основывается на использовании квалифицированных имен столбцов. Идея этого подхода (более раннего в истории SQL) заключается в том, что с любой таблицей, ссылка на которую содержится в списке раздела FROM, можно связать некоторое имя-псевдоним (в стандарте оно называется correlation name 7Причины использования в стандарте этого термина будут более понятны после ознакомления в следующей лекции с механизмом коррелирующих вложенных подзапросов . ). Тогда, если с такой таблицей A связан псевдоним Z, то в пределах оператора выборки можно ссылаться на любой столбец a таблицы A по квалифицированному имени Z.a. Мы обсудим это подробнее в следующем подразделе. Пока же будем считать, что имена всех столбцов таблицы T определены и различны.

На втором шаге выполняется раздел WHERE. Условное выражение ( conditional_expression ) этого раздела применяется к каждой строке таблицы T, и результатом является таблица T1, содержащая те и только те строки таблицы T, для которых результатом вычисления условного выражения является true. (Заголовки таблиц T и T1 совпадают.) Если раздел WHERE в операторе выборки отсутствует, то это трактуется как наличие раздела WHERE true 8Заметим, что эта форма раздела WHERE в языке SQL не допускается, поскольку после ключевого слова WHERE должно следовать булевское выражение, а true булевским выражением не является. т. е. T1 содержит те и только те строки, которые содержатся в таблице T. Обратите внимание на разницу в трактовке логических выражений в операторах выборки и в табличных ограничениях целостности. Логическое выражение раздела WHEREраздела HAVING ) оператора выборки разрешает выборку строки в том и только в том случае, когда результатом вычисления логического выражения на данной строке является true (значения false и unknown не являются разрешающими). Логическое выражение табличного ограничения целостности запрещает наличие строки в таблице в том и только в том случае, когда результатом вычисления логического выражения на данной строке является false (значения true и unknown не являются запрещающими).

Если в операторе выборки присутствует раздел GROUP BY, то он выполняется на третьем шаге. Каждый элемент списка имен столбцов ( column_name_commalist ), указываемого в этом разделе, должен быть одним из имен столбцов таблицы T1. В результате выполнения раздела GROUP BY образуется сгруппированная таблица T2, в которой строки таблицы T1 расставлены в минимальное число групп, таких, что во всех строках одной группы значения столбцов, указанных в списке имен столбцов раздела GROUP BY ( столбцов группировки ), одинаковы9Если говорить более точно, то в одной группе все строки, составленные из значений столбцов группировки, являются дубликатами. Заметим, что сгруппированные таблицы не могут являться окончательным результатом оператора выборки. Они существуют только на концептуальном уровне на стадии выполнения запроса, содержащего раздел GROUP BY.

Если в операторе выборки присутствует раздел HAVING, то он выполняется на следующем шаге. Условное выражение этого раздела применяется к каждой группе строк таблицы T2, и результатом является сгруппированная таблица T3, содержащая те и только те группы строк таблицы T2, для которых результатом вычисления условного выражения является true. Условное выражение раздела HAVING строится по синтаксическим правилам, общим для всех условных выражений, но обладает той спецификой, что применяется к группам строк, а не к отдельным строкам. Поэтому предикаты, из которых строится это условное выражение, должны быть предикатами на группу в целом. В них могут использоваться имена столбцов группировки ( инварианты группы ) и так называемые агрегатные функции ( COUNT, SUM, MIN, MAX, AVG ) от других столбцов. Мы обсудим агрегатные функции более подробно в следующих лекциях.

При наличии в запросе раздела HAVING, которому не предшествует раздел GROUP BY, таблица T1 рассматривается как сгруппированная таблица, состоящая из одной группы строк, без столбцов группирования. В этом случае логическое выражение раздела HAVING может состоять только из предикатов с агрегатными функциями, а результат вычисления этого раздела T3 либо совпадает с таблицей T1, либо является пустым.

Если в операторе выборки присутствует раздел GROUP BY, но отсутствует раздел HAVING, то это трактуется как наличие раздела HAVING true 10Заметим, что эта форма раздела HAVING в языке SQL не допускается, поскольку после ключевого слова HAVING должно следовать булевское выражение, а true булевским выражением не является. т. е. T3 содержит те и только те группы строк, которые содержатся в таблице T2.

После выполнения раздела WHERE (если в запросе отсутствуют разделы GROUP BY и HAVING, случай (a)) или явно или неявно заданного раздела HAVING (случай (b)) выполняется раздел SELECT. При выполнении этого раздела на основе таблицы T1 в случае (a) или на основе сгруппированной таблицы T3 в случае (b) строится таблица T4, содержащая столько строк, сколько строк или групп строк содержится в таблицах T1 или T3 соответственно. Число столбцов в таблице T4 зависит от числа элементов в списке элементов выборки ( select_item_commalist ) и от вида элементов.

Рассмотрим, каким образом формируются значения столбцов в таблице T4. Элемент списка выборки может задаваться одним из двух способов:

select_item ::= value_expression [ [ AS ] column_name ]
	| [ correlation_name . ] *

Сначала обсудим первый вариант. В этом случае каждый элемент списка элементов выборки соответствует столбцу таблицы T4. Столбцу может быть явным образом приписано имя (когда и зачем могут использоваться имена таблицы T4, мы обсудим позже). Порядок формирования значения этого столбца для выделенных выше случаев (a) и (b) различается, и мы рассмотрим подобные случаи по отдельности.

В случае (a) выражение, содержащееся в элементе выборки, может содержать литеральные константы и вызовы функций со значениями соответствующих типов (в том числе ниладические). Кроме того, в выражении могут использоваться имена столбцов таблицы T1 11Обратите внимание, что в выражении элемента выборки не обязательно должно содержаться хотя бы одно имя столбца. Допускается наличие чисто контактного выражения, значение которого будет повторяться в данном столбце всех строк таблицы TF. Кроме того, заметим, что в соответствии с определением value_expression элемент списка выборки может быть запросом, возвращающим таблицу из одной строки с одним столбцом.. Выражение вычисляется для каждой строки таблицы T1, и именам столбцов соответствуют значения этих столбцов в данной строке таблицы T1.

В случае (b), как и в случае (a), выражение, содержащееся в элементе выборки, может содержать литеральные константы и вызовы функций. Но, в отличие от случая (a), в выражение могут входить непосредственно имена только тех столбцов таблицы T3, которые входили в список столбцов группировки раздела GROUP BY оператора выборки. (Если сгруппированная таблица T3 была образована за счет наличия раздела HAVING без присутствия раздела GROUP BY, то в выражении элемента выборки вообще нельзя непосредственно использовать имена столбцов таблицы T3 ). Имена других столбцов таблицы T3 могут использоваться только в конструкциях вызова агрегатных функций COUNT, SUM, MIN, MAX, AVG. Выражение вычисляется для каждой группы строк таблицы T3. Именам столбцов, входящих в выражение непосредственно, сопоставляются значения этих столбцов, которые соответствуют данной группе строк таблицы T3.

Во втором варианте спецификация элемента списка выборки вида [ Z. ]* является сокращенной формой записи списка Z.a1, Z.a2, …, Z.an, где a1, a2, …, an представляет собой полный список имен столбцов таблицы, псевдоним которой Z. 12Заметим, что любой элемент Z.ai этого неявно заданного списка может быть явно включен в список элементов выборки. Кстати, если в списке выборки присутствует явно или неявно заданный элемент вида Z.a, то в пределах запроса соответствующий столбец таблицы T4 получает тоже имя. Следует сделать три замечания. Во-первых, для именованной таблицы, входящей в список раздела FROM только один раз, можно использовать имя таблицы вместо псевдонима. Во-вторых, во втором варианте спецификации элемента списка выборки можно опустить псевдоним только в том случае, если в разделе FROM указана только одна таблица. В-третьих, в случае (b) второй вариант спецификации элемента выборки допустим только тогда, когда все столбцы таблицы с псевдонимом Z входят в список столбцов группировки раздела GROUP BY.

Итак, мы получили таблицу T4. Если в спецификации раздела SELECT отсутствует ключевое слово DISTINCT, или присутствует ключевое слово ALL, либо отсутствуют и ALL, и DISTINCT, то T4 является результатом выполнения раздела SELECT. В противном случае на завершающей стадии выполнения раздела SELECT в таблице T4 удаляются строки-дубликаты.

Если в операторе выборки не содержится раздел ORDER BY, то таблица T4 является результирующей таблицей запроса. Иначе на завершающей стадии выполнения запроса производится сортировка строк таблицы T4 в соответствии со списком элементов сортировки ( order_item_commalist ) раздела ORDER BY. В стандарте SQL:1999 элемент списка элементов сортировки имеет следующую синтаксическую форму:

order_item ::= value_expression [ collate_clause ] 
	[ { ASC | DESC } ]

Выполнение раздела ORDER BY производится следующим образом13Мы снова проигнорируем спецификацию раздела collate, связанную с использованием национальных наборов символов. Выбирается первый элемент списка сортировки, и строки таблицы T4 расставляются в порядке возрастания (если в элементе присутствует спецификация ASC ; при отсутствии спецификации ASC/DESC предполагается наличие ASC ) или в порядке убывания (при наличии спецификации DESC ) в соответствии со значениями выражения, содержащегося в данном элементе, которые вычисляются для каждой строки таблицы T4. Далее выбирается второй элемент списка сортировки, и в соответствии со значениями заданного в нем выражения и порядка сортировки расставляются строки, которые после первого шага сортировки образовали группы с одинаковым значением выражения первого элемента списка сортировки. Операция продолжается до исчерпания списка элементов сортировки. Результирующий отсортированный список строк является окончательным результатом запроса.

В общем случае выражение, входящее в элемент списка сортировки, основывается на именах столбцов таблицы T4 и именах столбцов таблицы, над которой вычислялся раздел SELECT ( T1 или T3 ). Идея состоит в том, что если некоторое выражение могло бы быть использовано в элементе списка выборки, то его можно использовать в элементе списка сортировки. В стандарте SQL:1999 присутствует ряд чисто технических ограничений на вид выражений, допустимых в элементах списка сортировки, если в запросе присутствуют разделы GROUP BY и/или HAVING и если в разделе SELECT присутствует спецификация DISTINCT. Но в любом случае это выражение может иметь вид a, где a - имя столбца таблицы T4.

Заметим, что в предыдущих версиях стандарта языка SQL, включая SQL/92, элемент списка сортировки определялся следующим синтаксическим правилом:

order_item ::= { column_name | unsigned_integer } 
	[ { ASC | DESC } ]

В качестве имени столбца ( column_name ) можно было использовать любое имя, вводимое для столбца таблицы T4 в элементе списка выборки. Вместо имени столбца можно было использовать его порядковый номер ( unsigned_integer ) в списке элементов выборки раздела SELECT. Как мы видели, в новом стандарте вторая возможность исключена. Доводом является не тот факт, что использование номеров столбцов противоречит реляционной модели. Использование номеров столбцов запрещено, поскольку не давало возможности применять в элементах списка сортировки выражения. Тем не менее, по нашему мнению, возможность использования номеров столбцов в течение долгого времени будет продолжать поддерживаться в коммерческих реализациях SQL, поскольку она применяется во многих существующих приложениях.

< Лекция 2 || Лекция 3: 12345 || Лекция 4 >
Алексей Ковтун
Алексей Ковтун

При попытке исполнения запроса:

CREATE DOMAIN EMP_NO AS INTEGER

    CHECK (VALUE BETWEEN 1 AND 10000);

Выдается ошибка: Неизвестный тип объекта "DOMAIN" в интсрукции CREATE, DROP или ALTER. 

Используется SQL Server MS SQL 2008R2

Александра Каева
Александра Каева