Разница между нотами 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 в синтаксис (+), это можно увидеть в разделе "Информация о предикате" плана выполнения.