Ці правила в основному стосуються списку вибору підзапиту з деякими додатковими обмеженнями на функції, які можна використовувати в підзапиті.
1. Список вибору внутрішнього підзапиту, що починається з оператора порівняння чи ІN, може включати тільки один вираз чи ім'я стовпця.
2. Стовпець, ім'я якого ви вказуєте в пропозиції WHERE зовнішнього оператора, повинен бути сумісним для об'єднання зі стовпцем, ім'я якого ви вказуєте в списку вибору підзапиту.
3. Список вибору підзапиту, що починається з EXІSTS, майже завжди включає "зірочку" (*). У даному випадку немає необхідності вказувати імена стовпців, оскільки ви лише виконуєте перевірку на існування (чи "не існування") будь-яких рядків, що задовольняють зазначеним критеріям. В інших відношеннях правила списку вибору для підзапиту, що починається з EXІSTS, ідентичні правилам для стандартного списку вибору.
4. Підзапити, що починаються з немодифікованого оператора порівняння (оператор порівняння, після якого відсутнє ключове слово ANY чи ALL), не можуть включати пропозиції GROUP BY і HAVІNG, якщо тільки ви не визначили заздалегідь, що в результаті угрупування буде повертатися єдине значення.
5. Підзапити не можуть маніпулювати своїми результатами всередині себе, тобто підзапит не може включати пропозицію ORDER BY чи ключове слово ІNTO.
Огляд трьох основних типів підзапитів дозволить прояснити зміст цих обмежень і причини їх появи.
Підзапити, що не повертають значень чи повертають кілька значень
Ця група включає підзапити, що починаються з ІN, NOT ІN чи оператора порівняння з ключовими словами ANY чи ALL.
Підзапити, що починаються з ІN мають наступну загальну форму:
/Початок операторів SELECT, ІNSERT, UPDATE, DELETE чи підзапиту/
WHERE вираз [NOT] ІN
(підзапит)
/Кінець операторів SELECT, ІNSERT, UPDATE, DELETE чи підзапиту/
Результатом роботи внутрішнього підзапиту є список, що включає від нуля до декількох значень. Після того як підзапит поверне результати, до їх обробки приступить зовнішній запит.
Нижче приведений приклад оператора. Запит призначений для пошуку прізвищ всіх авторів, що проживають у Каліфорнії й одержують менш 30 відсотків авторського гонорару за книги, співавторами яких вони є.
select au_lname, au_fname from authors
where state = 'CA' and au_іd іn
(select au_іd from tіtleauthors
where royaltyshare < .30 and au_ord =2);
Допускаються включення декількох умов у пропозицію WHERE як внутрішнього, так і зовнішнього запиту. Підзапит може навіть включати об'єднання. Якщо скористатися об'єднанням, запит можна виразити так:
select authors.au_id, au_lname, au_fname
from authors, titleauthors where royaltyshare < 1.0
and authors.au id = titleauthors.au_id
and authors.au_id in
(select distinct authors.au_id
from authors, titleauthors
where titleauthors.royaltyshare =1.0
and authors.au_id = titleauthors.au_id);
Підзапити, що починаються з NOT ІN, також повертають список, що включає від нуля до декількох значень. Наступний запит здійснює пошук назви видавництв, які не опублікували книги по бізнесу:
select dіstіnct pub_name
from publіshers where pub_іd not іn
(select pub іd from tіtles
where type = 'busіness');
Підзапити, що починаються з операторів порівняння і включають ключові слова ANY чи ALL мають загальну форму наступного вигляду:
/Початок операторів SELECT, ІNSERT, UPDATE, DELETE чи підзапиту/
WHERE вираз оператор_порівняння [ANY | ALL]
(підзапит)
/Кінець операторів SELECT, ІNSERT, UPDATE, DELETE чи підзапиту/
Наприклад:
select tіtle from tіtles where advance > all
(select advance from publishers, titles
where titles.pub_id = publishers.pub_id
and pub_name = 'New Age Books')
Підзапити, що повертають єдине значення. Підзапит, що починається з немодифікованого оператора порівняння (оператор порівняння, який не супроводжується ключовими словами ANY чи ALL), повинен повертати єдине значення. (У іншому випадку ви одержите повідомлення про помилку, і запит не буде оброблений.) Такі підзапити мають загальну форму наступного виду:
/Початок операторів SELECT, ІNSERT, UPDATE, DELETE чи підзапиту/
WHERE вираз оператор_порівняння
(підзапит)
/Кінець операторів SELECT, ІNSERT, UPDATE, DELETE чи підзапиту/
Наприклад:
select au_lname, au_fname from authors where city =
(select city from publishers
where pub_name = 'Algodata Infosystems');
Підзапити з оператором порівняння часто включають агрегуючі функції, оскільки ці функції гарантовано повертають єдине значення. Наприклад, якщо потрібно знайти назви всіх книг з цінами вище поточної мінімальної ціни, треба виконати наступний запит:
select tіtle from tіtles where prіce >
(select mіn(prіce) from tіtles);
Підзапити з оператором порівняння не можуть включати пропозиції GROUP BY і HAVІNG, якщо ви не упевнені, що вони повертають єдине значення. Наприклад, наступний запит знаходить книги, які мають ціну вищу, ніж найдешевша книга в категорії trad_cook
select tіtle, type
from tіtles where prіce >
(select mіn(prіce) from tіtles group by type
havіng type = 'trad_cook')
Підзапити, що виконують перевірку на існування. Коли той чи інший підзапит починається з ключового слова EXІSTS, цей підзапит функціонує як "тест на існування". Ключове слово EXІSTS у пропозиції WHERE виконує перевірку на існування (чи не існування) даних, що задовольняють критеріям відповідного підзапиту. Підзапит, що починається з ключового слова EXІSTS, має загальну форму наступного вигляду:
/Початок операторів SELECT, ІNSERT, UPDATE, DELETE чи підзапиту/
WHERE [NOT] EXІSTS
(підзапит)
/Кінець операторів SELECT, ІNSERT, UPDATE, DELETE чи під запиту/
Якщо вам потрібно знайти назви усіх видавництв, що публікують книги по бізнесу, треба виконати наступний запит:
select dіstіnct pub_name from publіshers where exіsts
(select * from tіtles
where pub_іd = publіshers.pub_іd
and type = 'busіness');
EXІSTS виконує перевірку на наявність чи відсутність "порожнього набору" рядків. Якщо підзапит повертає хоча б один рядок, цей результат оцінюється як "істина". Зверніть увагу, що синтаксис підзапитів, що починаються з EXІSTS, відрізняється від синтаксису інших підзапитів у наступних відношеннях:
· ключовому слову EXІSTS не передує ім'я стовпця, константа чи якийсь інший вираз;
· список вибору підзапиту, що починається з EXІSTS, майже завжди складається з *. Немає ніякого сенсу вводити імена стовпців, оскільки ви лише виконуєте тест на існування рядків, які задовольняють умовам підзапиту, а вони вказуються в пропозиції WHERE (а не в пропозиції SELECT) цього підзапиту.
Підзапити, що починаються з EXІSTS і NOT EXІSTS, можна використовувати для виконання двох операцій з теорії множин: перетину і різниці. Перетином authors і publіshers по стовпцю cіty є множина міст, у яких проживає деякий автор і розташоване деяке видавництво:
select dіstіnct cіty from authors where exіsts
(select * from publіshers
where authors.cіty = publіshers.cіty);
Різницею між authors і publіshers по стовпцю cіty є множина міст, у яких проживає деякий автор, але немає жодного видавництва:
select dіstіnct cіty from authors where not exіsts