Разница между нотацией Oracle plus ( + ) и нотацией ANSI JOIN?

в чем разница между использованием нотации oracle plus (+) по стандарту ansi join нотации?

есть ли разница в производительности?

является ли нотация plus устаревшей?

8 ответов


насколько мне известно, в (+) нотация присутствует только для обратной совместимости, потому что Oracle дебютировала до того, как был введен стандарт ANSI для соединений. Он специфичен для Oracle, и вы должны избегать его использования в новом коде, когда доступна эквивалентная версия, совместимая со стандартами.

Edit: кажется, есть различия между этими двумя, и (+) нотация имеет ограничения, которых нет в синтаксисе соединения ANSI. Сами Oracle не рекомендуется использовать (+) нотации. Полное описание здесь Справочник по языку SQL базы данных Oracle® 11g Выпуск 1 (11.1):

Oracle рекомендует использовать FROM п. OUTER JOIN синтаксис, а не оператор Oracle join. Внешние запросы соединения, использующие оператор Oracle join (+) действуют следующие правила и ограничения, которые не распространяются на FROM п. OUTER JOIN синтаксис:

  • вы не можете указать (+) оператор в блоке запроса, который также содержит FROM синтаксис предложения join.
  • на (+) оператор может отображаться только в WHERE предложение или, в контексте левой корреляции (при указании TABLE предложения) в FROM предложение, и может применяться только к столбцу таблицы или представления.
  • если A и B соединены несколькими условиями соединения, то вы должны использовать (+) оператор во всех этих условиях. Если вы этого не сделаете, то Oracle Database вернет только строки, полученные в результате простого соединения, но без предупреждения или ошибки, чтобы сообщить вам, что у вас нет результатов внешнего соединения.

  • на не создает внешнего соединения, если во внешнем запросе указана одна таблица, а во внутреннем-другая.

  • вы не можете использовать (+) operator to outer-присоединить таблицу к себе, хотя самостоятельные соединения действительны.

например, недопустимо следующее утверждение:

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;
  • на может применяться только к столбцу, а не к произвольному выражению. Однако, произвольное выражение может содержать один или несколько столбцов, помеченных (+) оператора.

  • A WHERE условие, содержащее (+) оператор не может быть объединен с другим условием с помощью OR логический оператор.

  • A WHERE условие не может использовать IN условие сравнения для сравнения столбца, помеченного (+) оператор с выражением.

если WHERE предложение содержит условие, которое сравнивает столбец из таблицы B с константой, затем (+) оператор должен быть применен к колонне, так что Oracle возвращает строки из таблицы A, для которых он создал нули для этого столбца. В противном случае Oracle возвращает только результаты простого соединения.

в запросе, который выполняет внешние соединения более двух пар таблиц, одна таблица может быть пустой таблицы, созданные только для одной таблицы. По этой причине вы не можете применить (+) оператор для столбцов B в условии соединения для A и B и условие соединения для B и C. обратитесь к SELECT синтаксис внешнего соединения.


нотация по-прежнему поддерживается с Oracle 10 (и я считаю, что 11). Его использование считается "старомодным", а также не является переносимой базой данных, как синтаксис ANSI JOIN. Это также считается гораздо менее читаемым, хотя, если вы пришли из фона+, привыкание к ANSI JOIN может занять немного времени. Важно знать, прежде чем бросать кирпичи в Oracle, что они разработали свой синтаксис + до того, как комитет ANSI завершил определения для присоединяется.

нет разницы в производительности; они выражают одно и то же.

Edit: по "не как портативный" я должен был сказать "поддерживается только в Oracle SQL"


Я согласен с ответом Тони Миллера и хотел бы добавить, что есть также несколько вещей, которые вы не можете сделать с (+) synthax:

  • вы не можете полное внешнее соединение двух таблиц, вы должны сделать это вручную с объединением всех двух соединений,
  • вы не можете присоединить внешнюю таблицу к двум или более таблицам, вам нужно вручную создать подзапрос (т. е.: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 join это то, что нет никаких шансов случайно создать декартова произведения. С большим количеством таблиц, есть шанс пропустить подразумевается join с более старым синтаксисом Oracle join, однако, с синтаксисом ANSI вы не можете пропустить ни одного соединения, как вы должны явно упоминать о них.

разницу между внешнее соединение Oracle синтаксис и синтаксис ANSI/ISO.

ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ -

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);

ПОЛНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ -

перед родной поддержкой хэша full outerjoin в 11gR1 Oracle внутренне преобразует полное внешнее соединение следующим образом -

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 standared присоединиться обозначения может быть используется в любых СУБД (например, Sql Server, MySql и т. д.). В противном случае нет никакой разницы между обозначениями Oracle (+) и ANSI standared Join notation.

Если вы используете стандартную нотацию соединения ANSI в Sql-запросе, вы можете использовать тот же запрос в любой СУБД. и, если вы не перенос базы данных от Oracle до любой другой СУБД в этом состоянии вы должны использовать синтаксис ANSI.


Я использую (+) нотацию, потому что почти все связанные с Oracle Apps R12 запросы основаны на этом. Я не видел ни одного SQL-запроса со стандартным выражением "join" в запросах Oracle APPS(даже тех, которые предоставлены самим Oracle). Если вы мне не верите, просто google любую информацию, связанную с Oracle apps. Например: запросы, связанные с основными средствами


  1. используйте явные соединения, а не неявные (независимо от того, являются ли они внешними соединениями или нет), что гораздо проще случайно создать декартово произведение с неявными соединениями. С явными соединениями вы не можете "случайно" создать его. Чем больше таблиц, тем выше риск, что вы пропустите одно условие соединения.
  2. в основном ( + ) сильно ограничен по сравнению с соединениями ANSI. Кроме того, он доступен только в Oracle, тогда как синтаксис соединения ANSI поддерживается всеми основными СУБД
  3. SQL не начнет работать лучше после миграции в синтаксис ANSI - это просто другой синтаксис.
  4. Oracle настоятельно рекомендует использовать более гибкий синтаксис предложения FROM join, показанный в предыдущем примере. В прошлом были некоторые ошибки с синтаксисом ANSI, но если вы идете с последними 11.2 или 12.1, которые уже должны быть исправлены.
  5. использование операторов JOIN гарантирует, что ваш SQL-код совместим с ANSI и, таким образом, позволит интерфейсное приложение будет легче переноситься для других платформ баз данных.
  6. условия соединения имеют очень низкую селективность на каждой таблице и высокую селективность на кортежах в теоретическом перекрестном произведении. Условия в WHERE обычно имеют гораздо более высокую избирательность.
  7. Oracle внутренне преобразует синтаксис ANSI в синтаксис ( + ), это можно увидеть в разделе сведений о предикате плана выполнения.