Шаг 29 - Снова SELECT - имена, псевдонимы...

Итак, продолжим, в нашей учебной базе данных, вернее сказать, в учебных табличках, есть две таблицы с одинаковыми именами столбцов. Это таблицы 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. Вот теперь, надеюсь, понятно, как избежать излишней писанины с помощью псевдонимов таблиц. Можете пробовать сами для закрепления материала! :)


Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Летучий Сергей - 21.09.2003