Левое внешнее объединение с помощью знака + в Oracle 11g - PullRequest
78 голосов
/ 02 июля 2011

Может ли кто-нибудь сказать мне, являются ли ниже 2 запроса примером левого внешнего соединения или правого внешнего соединения ??

Table Part:
Name         Null?       Type
PART_ID      NOT NULL    VARCHAR2(4)
SUPPLIER_ID              VARCHAR2(4)

PART_ID SUPPLIER_ID
P1      S1
P2      S2
P3  
P4  

Table Supplier:
Name            Null?     Type
SUPPLIER_ID NOT NULL      VARCHAR2(4)
SUPPLIER_NAME   NOT NULL  VARCHAR2(20)

SUPPLIER_ID  SUPPLIER_NAME
S1           Supplier#1
S2           Supplier#2
S3           Supplier#3

Показать все детали, независимо от того, поставляет их поставщик или нет:

SELECT P.Part_Id, S.Supplier_Name
FROM Part P, Supplier S
WHERE P.Supplier_Id = S.Supplier_Id (+)

SELECT P.Part_Id, S.Supplier_Name
FROM Part P, Supplier S
WHERE S.Supplier_Id (+) = P.Supplier_Id

Ответы [ 4 ]

179 голосов
/ 03 июля 2011

TableA LEFT OUTER JOIN TableB эквивалентно TableB RIGHT OUTER JOIN Table A.

В Oracle (+) обозначает «необязательную» таблицу в JOIN.Итак, в вашем первом запросе это P LEFT OUTER JOIN S.В вашем втором запросе это S RIGHT OUTER JOIN P. Они функционально эквивалентны.

В терминологии RIGHT или LEFT указывают, какая сторона объединения всегда имеет запись, а другая сторона может быть нулевой.Так что в P LEFT OUTER JOIN S, P всегда будет иметь запись, потому что она находится на LEFT, но S может быть нулевым.

См. этот пример с java2s.com для дополнительного объяснения.


Чтобы пояснить, я полагаю, я говорю, что терминология не имеет значения, поскольку она существует только для визуализации.Важно то, что вы понимаете концепцию его работы.


ПРАВО против ЛЕВЫХ

Я видел некоторую путаницу в том, что важно при определении ПРАВО против ЛЕВЫХ в неявном синтаксисе соединения.

LEFT OUTER JOIN

SELECT *
FROM A, B
WHERE A.column = B.column(+)

RIGHT OUTER JOIN

SELECT *
FROM A, B
WHERE B.column(+) = A.column

Все, что я сделал, это поменялся сторонами терминов в предложении WHERE, но они все еще функциональныэквивалент.(См. Выше в моем ответе для получения дополнительной информации об этом.) Размещение (+) определяет ПРАВО или ВЛЕВО.(В частности, если (+) справа, это ЛЕВОЕ СОЕДИНЕНИЕ. Если (+) слева, то это ПРАВОЕ СОЕДИНЕНИЕ.)


Типы JOIN

Два стиля JOIN - это неявные JOINы и явные JOINs .Это разные стили написания JOIN, но они функционально эквивалентны.

См. этот вопрос SO .

Неявные JOIN просто перечисляют все таблицы вместе,Условия соединения указаны в предложении WHERE.

Неявное JOIN

SELECT *
FROM A, B
WHERE A.column = B.column(+)

Явные соединения вместо этого связывают условия соединения с включением определенной таблицыв предложении WHERE.

Явное соединение

SELECT *
FROM A
LEFT OUTER JOIN B ON A.column = B.column

Эти неявные соединения могут быть более сложными для чтения и понимания, и они также имеют несколько ограничений, так какусловия соединения смешиваются в других условиях WHERE.Таким образом, неявные соединения обычно рекомендуются в пользу явного синтаксиса.

8 голосов
/ 03 июля 2011

Эти два запроса выполняют OUTER JOIN.См. Ниже

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

  • Нельзя указать (+) оператор в блоке запроса, который также содержит синтаксис объединения предложения FROM.

  • Оператор (+) может появляться только в предложении WHERE или в контексте левой корреляции (когдауказание предложения TABLE) в предложении FROM и может применяться только к столбцу таблицы или представления.

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

  • Оператор (+) не создает внешнее соединение, если вы указали одну таблицу во внешнем запросе, а другую таблицу - во внутреннем запросе.

  • Нельзя использовать (+)оператор для внешнего соединения таблицы с самим собой, хотя самостоятельные соединения допустимы.Например, следующий оператор недопустим:

    -- The following statement is not valid:
    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
       ORDER BY e1.employee_id, e1.manager_id, e2.employee_id;
    
  • Оператор (+) может бытьприменяется только к столбцу, а не к произвольному выражению.Однако произвольное выражение может содержать один или несколько столбцов, помеченных оператором (+).

  • Условие WHERE, содержащее оператор (+), нельзя объединить с другим условием, используя логическое ИЛИoperator.

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

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

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

Взято из http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/queries006.htm

2 голосов
/ 12 октября 2016

Я видел некоторые противоречия в ответах выше, я только что попробовал следующее на Oracle 12c, и следующее правильно:

ВЛЕВО НАРУЖНОЕ СОЕДИНЕНИЕ

SELECT *
FROM A, B
WHERE A.column = B.column(+)

ПРАВО НАРУЖНОЕ СОЕДИНЕНИЕ

SELECT *
FROM A, B
WHERE B.column(+) = A.column
0 голосов
/ 25 сентября 2014

В этой теме есть неверная информация.Я скопировал и вставил неверную информацию:

СЛЕВА ВНЕШНЕГО СОЕДИНЕНИЯ

SELECT *
FROM A, B
WHERE A.column = B.column(+)

ПРАВО НАРУЖНОГО СОЕДИНЕНИЯ

SELECT *
FROM A, B
WHERE B.column(+) = A.column

Выше НЕПРАВИЛЬНО !!!!!Оно задом наперед.Как я определил, что это неверно, можно узнать из следующей книги:

Oracle OCP Введение в Oracle 9i: Руководство по экзамену SQL .Таблица 3-1 содержит хорошее резюме по этому вопросу.Я не мог понять, почему мой конвертированный SQL не работал должным образом, пока я не пошел в старую школу и посмотрел печатную книгу!

Вот краткое изложение этой книги, строка за строкой:

Синтаксис внешнего соединения Oracle:

from tab_a a, tab_b b,                                       
where a.col_1 + = b.col_1                                     

Эквивалент ANSI / ISO:

from tab_a a left outer join  
tab_b b on a.col_1 = b.col_1

Обратите внимание, что это обратное тому, что опубликовано выше.Я полагаю, что в этой книге могут быть ошибки, однако я доверяю этой книге больше, чем тому, что есть в этой теме.Это руководство к экзамену для громкого крика ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...