Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка по SQL.DOC
Скачиваний:
205
Добавлен:
01.05.2014
Размер:
1.16 Mб
Скачать

8.2. Значения, которые могут выдавать подзапросы

Подзапрос должен возвращать одно и только одно значение.

Если в предыдущем подзапросе назначить условие snum “ WHERE city = “London” вместо “WHERE sname = ‘Motika”, то можно получить несколько различных значений. Это может сделать уравнение в предикате основного запроса невозможным для оценки истинности или неистинности, и команда выдаст ошибку.

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

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

DISTINCT С ПОДЗАПРОСАМИ

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

найти все приобретения для тех продавцов, которые обслуживают

Hoffmanа ( cnum = 2001 ).

Имеется один способ, чтобы сделать это:

SELECT *

FROM Orders

WHERE snum =

( SELECT DISTINCT snum

FROM Orders

WHERE cnum = 2001 );

=============== SQL Execution Log ==============

| =============================================== |

| onum amt odate cnum snum |

| ----- --------- --------- ------ ------- |

| 3003 767.19 10/03/1990 2001 1001 |

| 3008 4723.00 10/05/1990 2006 1001 |

| 3011 9891.88 10/06/1990 2006 1001 |

================================================

Подзапрос установил что значение поля snum совпало с Hoffman - 1001, и

затем основной запрос выделил все приобретения с этим значением snum из таблицы Приобретений( не разбирая, относятся они к Hoffman или нет). Так как каждый заказчик назначен к одному и только этому продавцу, мы знаем, что каждая строка в таблице Приобретений с данным значением cnum должна иметь такое же значение snum. Однако так как там может быть любое число таких строк, подзапрос мог бы вывести много ( хотя и идентичных ) значений snum для данного поля cnum. Аргумент DISTINCT предотвращает это. Если наш подзапрос возвратит более одного значения, это будет указывать на

ошибку в наших данных - хорошая вещь для знающих об этом.

.

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

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

< скалярная форма > < оператор > < подзапрос >,

а, не < подзапрос > < оператор > < скалярное выражение >

или, < подзапрос > < оператор > < подзапрос >.

Другими словами, вы не должны записывать предыдущий пример так:

SELECT *

FROM Orders

WHERE ( SELECT DISTINCT snum

FROM Orders

WHERE cnum = 2001 )

= snum;

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

Соседние файлы в предмете Базы данных