В чем разница между использованием оракула плюс обозначение (+)
над стандартной записью ansi join
?
Есть ли разница в производительности?
Является ли обозначение "плюс" устаревшим?
В чем разница между использованием оракула плюс обозначение (+)
над стандартной записью ansi join
?
Есть ли разница в производительности?
Является ли обозначение "плюс" устаревшим?
AFAIK, нотация (+)
присутствует только для обратной совместимости, потому что Oracle дебютировала с ней до того, как был введен стандарт ANSI для соединений. Он специфичен для Oracle, и вам следует избегать его использования в новом коде при наличии эквивалентной версии, соответствующей стандартам.
Кажется, между ними есть различия, и нотация (+)
имеет ограничения, которых нет в синтаксисе соединения ANSI. Сами Oracle рекомендуют не использовать нотацию (+)
.
Полное описание здесь, в справочнике по языку Oracle® Database SQL
11g, выпуск 1 (11.1):
Oracle рекомендует использовать синтаксис предложения
FROM
OUTER JOIN
, а не оператор соединения Oracle. На запросы внешнего соединения, использующие оператор соединения Oracle(+)
, распространяются следующие правила и ограничения, которые не применяются к синтаксису предложенияFROM
OUTER JOIN
:
- Вы не можете указать оператор
(+)
в блоке запроса, который также содержит синтаксис объединения предложенийFROM
.- Оператор
(+)
может появляться только в предложенииWHERE
или, в контексте левой корреляции (при указании предложенияTABLE
) в предложенииFROM
, и может применяться только к столбцу таблицы или посмотреть.- Если A и B объединены несколькими условиями соединения, то вы должны использовать оператор
(+)
во всех этих условиях. Если вы этого не сделаете, то Oracle Database вернет только строки, полученные в результате простого соединения, но без предупреждения или ошибки, сообщив вам, что у вас нет результатов внешнего соединения.- Оператор
(+)
не создает внешнее соединение, если вы указали одну таблицу во внешнем запросе, а другую - во внутреннем запросе.- Вы не можете использовать оператор
(+)
для внешнего соединения таблицы с самим собой, хотя самостоятельные объединения допустимы.Например, следующее утверждение недопустимо:
SELECT employee_id, manager_id FROM employees WHERE employees.manager_id(+) = employees.employee_id;
Однако допустимо следующее самостоятельное объединение:
SELECT e1.employee_id, e1.manager_id, e2.employee_id FROM employees e1, employees e2 WHERE e1.manager_id(+) = e2.employee_id;
- Оператор
(+)
можно применять только к столбцу, а не к произвольному выражению. Однако произвольное выражение может содержать один или несколько столбцов, помеченных оператором(+)
.- Условие
WHERE
, содержащее оператор(+)
, нельзя объединить с другим условием с помощью логического оператораOR
.- Условие
WHERE
не может использовать условие сравненияIN
для сравнения столбца, помеченного оператором(+)
, с выражением.Если предложение
WHERE
содержит условие, которое сравнивает столбец из таблицы B с константой, то к столбцу должен применяться оператор(+)
, чтобы Oracle возвращал строки из таблицы A, для которых он сгенерировал пустые значения для этого столбца., В противном случае Oracle возвращает только результаты простого объединения.В запросе, который выполняет внешние объединения более двух пар таблиц, одна таблица может быть сгенерированной нулем только для одной другой таблицы. По этой причине вы не можете применить оператор
(+)
к столбцам B в условии соединения для A и B и в условии соединения для B и C. Синтаксис для внешнего соединения см. вSELECT
.
Обозначения по-прежнему поддерживаются по версии Oracle 10 (и я считаю, что 11). Это использование считается "старомодным", а также не является портативной базой данных, как синтаксис ANSI JOIN. Он также считается гораздо менее читаемым, хотя, если вы исходите из фона +, привыкающего к ANSI JOIN, может занять немного времени. Важная вещь, которую нужно знать перед тем, как бросить кирпич в Oracle, заключается в том, что они разработали свой синтаксис + до того, как комитет ANSI завершил определения для объединений.
Нет разницы в производительности; они выражают одно и то же.
Изменить: "Не переносимым" я должен был сказать "поддерживается только в Oracle SQL"
Я согласен с ответом Тони Миллера и хотел бы добавить, что есть также несколько вещей, которые вы НЕ можете делать с (+) синтаксисом:
b.id = a.id (+) AND c.id = a.id (+)
не является приемлемым предложением)Наиболее полным ответом, очевидно, является nagul.
Добавление для тех, кто ищет быстрый перевод/сопоставление с синтаксисом ANSI:
--
-- INNER JOIN
--
SELECT *
FROM EMP e
INNER JOIN DEPT d ON d.DEPTNO = e.DEPTNO;
-- Synonym in deprecated oracle (+) syntax
SELECT *
FROM EMP e,
DEPT d
WHERE d.DEPTNO = e.DEPTNO;
--
-- LEFT OUTER JOIN
--
SELECT *
FROM EMP e
LEFT JOIN DEPT d ON d.DEPTNO = e.DEPTNO;
-- Synonym in deprecated oracle (+) syntax
SELECT *
FROM EMP e,
DEPT d
WHERE d.DEPTNO (+) = e.DEPTNO;
--
-- RIGHT OUTER JOIN
--
SELECT *
FROM EMP e
RIGHT JOIN DEPT d ON d.DEPTNO = e.DEPTNO;
-- Synonym in deprecated oracle (+) syntax
SELECT *
FROM EMP e,
DEPT d
WHERE d.DEPTNO = e.DEPTNO(+);
--
-- CROSS JOIN
--
SELECT *
FROM EMP e
CROSS JOIN DEPT d;
-- Synonym in deprecated oracle (+) syntax
SELECT *
FROM EMP e,
DEPT d;
--
-- FULL JOIN
--
SELECT *
FROM EMP e
FULL JOIN DEPT d ON d.DEPTNO = e.DEPTNO;
-- Synonym in deprecated oracle (+) syntax !NOT WORKING!
SELECT *
FROM EMP e,
DEPT d
WHERE d.DEPTNO (+) = e.DEPTNO(+);
Одна из веских причин использовать синтаксис ANSI для старого синтаксиса синтаксиса Oracle заключается в том, что существует вероятность непредвиденного создания декартова продукта. С большим количеством таблиц есть шанс пропустить соединение неявное со старым синтаксисом объединения Oracle, однако с синтаксисом ANSI вы не можете пропустить какое-либо соединение, поскольку вы должны явно указывать их.
Разница между сильным синтаксисом внешнего синтаксиса Oracle и синтаксисом ANSI/ISO.
LEFT OUTER JOIN -
SELECT e.last_name,
d.department_name
FROM employees e,
departments d
WHERE e.department_id = d.department_id(+);
SELECT e.last_name,
d.department_name
FROM employees e
LEFT OUTER JOIN departments d
ON (e.department_id = d.department_id);
ПРАВИЛЬНАЯ ВСТРОЕННАЯ РАБОТА -
SELECT e.last_name,
d.department_name
FROM employees e,
departments d
WHERE e.department_id(+) = d.department_id;
SELECT e.last_name,
d.department_name
FROM employees e
RIGHT OUTER JOIN departments d
ON (e.department_id = d.department_id);
ПОЛНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ -
До того, как встроенная поддержка хэш-функции полностью нарушена в 11gR1, Oracle внутренне преобразует FULL OUTER JOIN следующим образом -
SELECT e.last_name,
d.department_name
FROM employees e,
departments d
WHERE e.department_id = d.department_id(+)
UNION ALL
SELECT NULL,
d.department_name
FROM departments d
WHERE NOT EXISTS
(SELECT 1 FROM employees e WHERE e.department_id = d.department_id
);
SELECT e.last_name,
d.department_name
FROM employees e
FULL OUTER JOIN departments d
ON (e.department_id = d.department_id);
Посмотрите это.
Обозначение Oracle (+) используется только в Oracle, специально для поставщика. И ANSI, стандартная запись регистрации может быть использована в любой СУБД (например, Sql Server, MySql и т.д.). В противном случае нет разницы между нотами Oracle (+) и стандартными нотами объединения ANSI.
Если вы используете стандартную запись регистрации ANSI в своем Sql Query, вы можете использовать тот же запрос в любой СУБД. И, если вы портируете вашу базу данных от Oracle к любой другой RDBMS в этом состоянии вам нужно использовать синтаксис ANSI.
Я использую (+) нотацию, потому что на этом основаны почти все запросы Oracle, связанные с r12. Я не видел ни одного SQL-запроса со стандартным выражением "join" в запросах Oracle APPS (даже тех, которые предоставлены самим Oracle). Если вы мне не верите, просто перейдите по любой информации, связанной с приложениями Oracle. Например: Запросы, связанные с основными средствами