Разница между нотами Oracle plus (+) и ansi JOIN-нотация?
В чем разница между использованием оракула плюс обозначение (+)
над стандартной записью ansi join
?
Есть ли разница в производительности?
Является ли обозначение "плюс" устаревшим?
Ответы
Ответ 1
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
.
Ответ 2
Обозначения по-прежнему поддерживаются по версии Oracle 10 (и я считаю, что 11). Это использование считается "старомодным", а также не является портативной базой данных, как синтаксис ANSI JOIN. Он также считается гораздо менее читаемым, хотя, если вы исходите из фона +, привыкающего к ANSI JOIN, может занять немного времени. Важная вещь, которую нужно знать перед тем, как бросить кирпич в Oracle, заключается в том, что они разработали свой синтаксис + до того, как комитет ANSI завершил определения для объединений.
Нет разницы в производительности; они выражают одно и то же.
Изменить: "Не переносимым" я должен был сказать "поддерживается только в Oracle SQL"
Ответ 3
Я согласен с ответом Тони Миллера и хотел бы добавить, что есть также несколько вещей, которые вы НЕ можете делать с (+) синтаксисом:
- Вы не можете ПОЛНОСТЬЮ ВСТУПИТЬ В ДРУГИЕ таблицы, вам нужно сделать это вручную с помощью UNION ALL из двух объединений,
- Вы не можете вставлять таблицу в две или более таблицы, вам нужно вручную создать подзапрос (т.е.:
b.id = a.id (+) AND c.id = a.id (+)
не является приемлемым предложением)
Ответ 4
Наиболее полным ответом, очевидно, является 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(+);
Ответ 5
Одна из веских причин использовать синтаксис 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);
Посмотрите это.
Ответ 6
Обозначение Oracle (+) используется только в Oracle, специально для поставщика. И ANSI, стандартная запись регистрации может быть использована в любой СУБД (например, Sql Server, MySql и т.д.). В противном случае нет разницы между нотами Oracle (+) и стандартными нотами объединения ANSI.
Если вы используете стандартную запись регистрации ANSI в своем Sql Query, вы можете использовать тот же запрос в любой СУБД. И, если вы портируете вашу базу данных от Oracle к любой другой RDBMS в этом состоянии вам нужно использовать синтаксис ANSI.
Ответ 7
Я использую (+) нотацию, потому что на этом основаны почти все запросы Oracle, связанные с r12. Я не видел ни одного SQL-запроса со стандартным выражением "join" в запросах Oracle APPS (даже тех, которые предоставлены самим Oracle). Если вы мне не верите, просто перейдите по любой информации, связанной с приложениями Oracle. Например: Запросы, связанные с основными средствами
Ответ 8
- Используйте явные JOIN, а не имплицитные (независимо от того, являются ли они внешними объединениями или нет) заключается в том, что намного проще создать декартовский продукт с неявными объединениями. С явным JOINs вы не можете "случайно" создать его. Чем больше таблиц задействовано, тем выше риск того, что вы пропустите одно условие соединения.
- В принципе (+) сильно ограничен по сравнению с ANSI-соединениями. Кроме того, он доступен только в Oracle, тогда как синтаксис соединения ANSI поддерживается всеми основными СУБД
- SQL не будет работать лучше после перехода на синтаксис ANSI - это просто другой синтаксис.
- Oracle настоятельно рекомендует использовать более гибкий синтаксис соединения предложения FROM, показанный в предыдущем примере. Раньше были некоторые ошибки с синтаксисом ANSI, но если вы идете с последними 11.2 или 12.1, которые должны быть исправлены уже.
- Использование операторов JOIN гарантирует, что ваш код SQL соответствует требованиям ANSI и, таким образом, позволит более легко переносить внешнее приложение для других платформ баз данных.
- Условия соединения имеют очень низкую избирательность по каждой таблице и высокую селективность по кортежам в теоретическом кросс-продукте. Условия в заявлении where обычно имеют гораздо более высокую избирательность.
- Oracle внутренне преобразует синтаксис ANSI в синтаксис (+), это можно увидеть в разделе "Информация о предикате" плана выполнения.