В лекции № 7 "Введение в Oracle SQL" в подразделе "Несамостоятельность группировки с обобщениями ROLLUP, CUBE и GROUPING SETS" представленная таблица сравнения содержит ошибки - окончания запросов пропущены. Видимо, ошибки вызваны некорректным переносом материала лекции. |
Соединения таблиц в предложении SELECT
Синтаксис для операции соединения, разрешенный с версии 9
Приводимый ранее способ записи полуоткрытого соединения является собственным решением Oracle (он взят из потерявшего силу стандарта SQL 1986 года и сейчас является нестандартизованным элементом диалекта SQL Oracle). В сложных запросах он может оказаться неудобочитаемым и провоцировать ошибки программирования. С версии 9 Oracle можно (и рекомендуется) для записи разных видов соединений использовать специально разработанные в стандарте SQL:1999 синтаксические конструкции. Они рассматриваются ниже.
Закрытые соединения
Пример записи обычного (внутреннего, или закрытого) соединения в соответствии с SQL:1999:
SELECT e.ename, d.dname FROM emp e INNER JOIN dept d ON ( e.deptno = d.deptno ) ;
Обратите внимание, что такая формулировка разрешает привести в конструкции ON любое условное выражение (<=, <>, LIKE и так далее), например:
SELECT e.ename, e.sal, s.grade FROM emp e INNER JOIN salgrade s ON ( e.sal BETWEEN s.losal AND s.hisal ) ;
Если же, как в предпоследнем случае, речь идет об эквисоединении (сравнении на совпадение величин) с одинаковыми названиями столбцов приравниваемых значений, годится и иная формулировка:
SELECT e.ename, d.dname FROM emp e INNER JOIN dept d USING ( deptno ) ;
У формулировки INNER JOIN … USING есть отличие от формулировки INNER JOIN … ON: во внутреннем декартовом произведении строк таблиц, которое строится фразой FROM в соответствии с логической схемой обработки предложения SELECT (приводилась выше) автоматически удаляются повторяющиеся столбцы. Это свойство унаследовано от реляционного соединения, где из результата автоматически удаляются одинаковые атрибуты (это не то же, что одинаково названные столбцы в таблицах SQL).
Упражнение. Сравните два результата, работы фразы FROM (в приводимых запросах кроме действий во фразе FROM по сути ничего не делается):
SELECT * FROM emp e INNER JOIN dept d ON e.deptno = d.deptno; SELECT * FROM emp INNER JOIN dept USING ( deptno );
Как следствие (вполне логичное) соединения столбцы, участвующие в соединении, не требуют уточнения именем таблицы при ссылке на них в других местах предложения, например:
SELECT e.ename, d.dname, deptno FROM emp e INNER JOIN dept d USING ( deptno ) ;
С другой стороны, когда заходит речь о самосоединении, это может приводить к проблеме:
SQL> SELECT * FROM dept INNER JOIN dept USING ( deptno ); SELECT * FROM dept INNER JOIN dept USING ( deptno ) * ERROR at line 1: ORA-00918: column ambiguously defined
Успокаивает то, что с точки зрения приложения подобные запросы редко имеют смысл. Избавиться от этой ошибки Oracle можно введением псевдонимов. Следующие два запроса не приведут к ошибке:
SELECT * FROM dept a INNER JOIN dept b USING ( deptno ); SELECT * FROM dept INNER JOIN ( SELECT * FROM dept ) USING ( deptno ) ;
Первый из них формально, а второй фактически не будет считаться самосоединением.
Два полуоткрытых и открытое соединения
Примеры (внешних) полуоткрытых соединений:
SELECT e.ename, d.dname FROM emp e LEFT OUTER JOIN dept d USING ( deptno ) ; SELECT e.ename, d.dname FROM emp e RIGHT OUTER JOIN dept d USING ( deptno ) ;
Пример (внешнего) открытого соединения:
SELECT e.ename, d.dname FROM emp e FULL OUTER JOIN dept d USING ( deptno ) ;
Последнее предложение не имеет равносильной записи в "старом" синтаксисе Oracle.