Итак, продолжим, в нашей учебной базе данных, вернее сказать, в учебных табличках, есть две таблицы с одинаковыми именами столбцов. Это таблицы OFFICES и SALESREPS. В них обеих есть столбец с именем SALES. Что если по какой-либо причине нам понадобится дать, например, вот такой запрос: Показать имя, офис, и объем продаж каждого служащего.
Он будет выглядеть примерно так:
SELECT NAME, SALESREPS.SALES, CITY FROM SALESREPS, OFFICES WHERE REP_OFFICE = OFFICE /
После выполнения получаем ошибку Oracle Server:
SQL> SELECT NAME, SALES, CITY 2 FROM SALESREPS, OFFICES 3 WHERE REP_OFFICE = OFFICE 4 / SELECT NAME, ->SALES, CITY FROM SALESREPS, OFFICES WHERE REP_OFFICE = OFFICE ORA-00918: столбец определен неоднозначно
Здесь я стрелочкой показал какой столбец вызвал эту ошибку. Если бы мы дали обычный запрос, например, вот такого вида: Показать названия городов, в которых фактический объем продаж превышает плановый.
SELECT CITY, SALES FROM OFFICES WHERE SALES > TARGET /
Показать имена служащих, у которых объем продаж больше $1000.
SELECT NAME, SALES FROM SALESREPS WHERE SALES > 200 /
Эти однотабличные запросы сработали бы без ошибок, но нас это на сегодня не устраивает. Так как же поступать? А очень просто, нужно применить так называемое "полное имя столбца", что это значит? А, то, что мы должны однозначно идентифицировать столбец согласно необходимой нам логике запроса!
Примерно вот так: Показать имя, офис, и объем продаж каждого служащего.
SELECT NAME, SALESREPS.SALES, CITY FROM SALESREPS, OFFICES WHERE REP_OFFICE = OFFICE /
Соответственно получаем:
SQL> SELECT NAME, SALESREPS.SALES, CITY 2 FROM SALESREPS, OFFICES 3 WHERE REP_OFFICE = OFFICE 4 / NAME SALES CITY ------------------------------ ---------- ------------------------------ Вася Пупкин 367,911 Бубурино Маша Распутина 392,725 Красный Мотоцикл Филип Киркоров 474,05 Котрогайка Света Разина 299,912 Красный Мотоцикл Наташа Королева 142,594 Чугуевск Игорь Николаев 305,673 Чугуевск Крис Кельми 75,985 Бубурино Игорь Петров 361,865 Котрогайка Дима Маликов 286,775 Чугуевск Маша Сидорова 186,042 Запиндрищинск Максим Галкин 386,042 Чугуевск 11 rows selected
Вот теперь запрос сработал, так как мы от него и ожидали! Правда, запись оператора SELECT стала немного длиннее. Но это не столь существенно. :) Теперь давайте рассмотрим еще один аспект при работе с многотабличными запросами, а именно оператор вида SELECT *, который используется для чтения всех столбцов. Рассмотрим запрос вида: Сообщить всю информацию, о служащих и офисах где они работают.
SELECT * FROM SALESREPS, OFFICES WHERE REP_OFFICE = OFFICE /
После отправки его в SQL*Plus мы получим 14ть(!) столбцов, я не буду приводить результат запроса, так как это слишком громоздко, так что приведу только примерную конфигурацию вывода: Сообщить всю информацию, о служащих и офисах где они работают.
SELECT * FROM SALESREPS, OFFICES WHERE REP_OFFICE = OFFICE / EMPL_NUM NAME AGE REP_OFFICE TITLE HIRE_DATE MANAGER QUOTA . . . . . . . --------- -------------------- --------------- -------------------- ----------- --------- ---------- 105 Вася Пупкин 37 13 Рапорт продажа 12.02.1988 104 350 . . . . . . . 109 Маша Распутина 31 11 Рапорт продажа 12.10.1989 106 300 . . . . . . . . . .
При работе с тремя и более таблицами оператор вида SELECT * не практичен, и его применение в многотабличных запросах можно поставить под сомнение. Однако, если его использовать несколько не стандартно, то в общем его можно и применять, но осторожно, так как в некоторых стандартах такие "фортели" запрещены! :) Например, чтобы ограничить количество столбцов в предыдущем запросе можно записать: Сообщить всю информацию, о служащих и офисах где они работают.
SELECT SALESREPS.*, CITY, REGION FROM SALESREPS, OFFICES WHERE REP_OFFICE = OFFICE / SQL> SELECT SALESREPS.*, CITY, REGION 2 FROM SALESREPS, OFFICES 3 WHERE REP_OFFICE = OFFICE 4 /
Получим то же что и выше, но теперь столбцов будет одиннадцать, девять из таблицы SALESREPS, и два соответственно из таблицы OFFICES. Теперь делайте выводы относительно применять или не применять! :) Что ж, двигаемся дальше!
На очереди "ПСЕВДОНИМЫ ТАБЛИЦ".
Допустим, что у нас есть пользователь SAM с таблицей BIRTHDAYS, где содержатся дни рождения наших работников.
Тогда запрос вида:
SELECT SALESREPS.NAME, QUOTA, SAM.BIRTHDAYS.BIRTH_DAY FROM SALESREPS, BIRTHDAYS WHERE SALESREPS.NAME = SAM.BIRTHDAYS.NAME /
Должен выполниться и вывести то, что мы ожидаем, но при написании мы видим, что получаются слишком длинные имена для столбцов и таблиц выборки. Вот здесь могут пригодиться "ПСЕВДОНИМЫ ТАБЛИЦ". Общий синтаксис записи псевдонимов строится следующим образом:
------ FROM ---------- имя таблицы -------- ------- псевдоним таблицы -----, ------------------------------- , -----------------------------------
Перепишем наш предыдущий запрос используя псевдонимы таблиц:
SELECT S.NAME, S.QUOTA, B.BIRTHDAYS.BIRTH_DAY FROM SALESREPS S, SAM.BIRTHDAYS B WHERE S.NAME = B.NAME /
Теперь наглядно видно, что запись вида SAM.BIRTHDAYS B, где B и есть псевдоним таблицы, получается гораздо компактнее, и не нужно повторять сложные и трудно запоминаемые имена таблиц и столбцов. В некоторых SQL серверах допускается запись вида - SAM.BIRTHDAYS AS B, но в нашем случае достаточно записи SAM.BIRTHDAYS B. Вот теперь, надеюсь, понятно, как избежать излишней писанины с помощью псевдонимов таблиц. Можете пробовать сами для закрепления материала! :)