Oracle: Что делает `(+)` в предложении WHERE?

В приложении на базе Oracle, которое мы переносим (обобщенный), мы обнаружили следующее:

SELECT
    Table1.Category1,
    Table1.Category2,
    count(*) as Total,
    count(Tab2.Stat) AS Stat
FROM Table1, Table2
WHERE (Table1.PrimaryKey = Table2.ForeignKey(+))
GROUP BY Table1.Category1, Table1.Category2

Что делает (+) в предложении WHERE? Я никогда раньше не видел, чтобы его использовали таким образом.

Существуют также устаревшие операторы TSQL (SQL Server) *= и =*. Та же лодка.

user166390 08.01.2011 11:05

Я искал значение этих (+) в SQL-запросах для Oracle. И нет возможности искать (+) с помощью Google. Я направился в Stack Overflow, и поисковая система Stack Overflow дала мне нулевой результат для (+). Что неверно. Здесь, в Stack Overflow, есть как минимум два вопроса о значении (+). Хорошо бы поисковик поправить.

Nicolas Barbulesco 29.07.2013 18:55

Связанный: Разница между нотацией Oracle plus (+) и нотацией ansi JOIN?

Jonathan Lonowski 02.04.2014 07:25
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
61
4
61 422
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Это нотация левого внешнего соединения, отличная от ANSI. Начиная с Oracle9i, запутанный синтаксис внешнего соединения с использованием обозначения «(+)» был заменен синтаксисом внешнего соединения ISO 99.

Просто придирки: стандартный синтаксис OUTER JOIN был введен в SQL-92.

Bill Karwin 10.01.2009 03:46

Извините, ваш ответ был первым ... проголосовали за. Оставив шахту вверх, так как в ней есть дополнительная информация re: left vs right outer.

SquareCog 10.01.2009 03:48
Ответ принят как подходящий

В зависимости от того, с какой стороны "=" стоит знак "(+), он обозначает соединение ЛЕВОЕ ВНЕШНЕЕ или ПРАВО ВНЕШНЕЕ (в данном случае это левое внешнее соединение). Это старый синтаксис Oracle, который иногда предпочитают люди, которые выучили его первыми, так как им нравится, что это делает их код короче.

Лучше не использовать его для удобства чтения.

Спасибо за дополнительный лакомый кусочек об ориентации между (+) и =.

Jonathan Lonowski 10.01.2009 04:06

- .5 для того, чтобы сказать, что длиннее, более читабельно. a ++ труднее читать, чем a = a + 1. Я думаю, что это намного проще, если вы знаете, что это означает. Если вы не знаете, что это значит, откажитесь от моего кода.

Mark Brady 06.02.2009 00:28

@Mark - Я программировал на Perl как на родном языке последние 8 лет. Если вы не усвоили разницу между коротким и непонятным, пожалуйста, не трогайте МОЙ код!

SquareCog 06.02.2009 03:01

К сожалению, синтаксис соединения ANSI недоступен в Oracle 8. Поэтому в этом случае вам нужно придерживаться синтаксиса (+).

Cheekysoft 20.07.2009 14:27

К сожалению, MATERIALIZED VIEW с опциями FAST REFRESH ON COMMIT не поддерживает ANSI JOINS (Oracle 11). Так что в этом случае вам все равно понадобится синтаксис (+).

Sandre 28.12.2016 23:39

Как утверждали другие, синтаксис (+) является устаревшим, проприетарным синтаксисом, который Oracle использовал в течение многих лет для достижения тех же результатов, что и OUTER JOIN. Я предполагаю, что они приняли свой собственный синтаксис до того, как SQL-92 остановился на стандартном синтаксисе.

Запрос, эквивалентный показанному вами, с использованием стандартного синтаксиса SQL OUTER JOIN (который теперь поддерживается всеми основными реализациями СУБД) будет следующим:

SELECT
    Table1.Category1,
    Table1.Category2,
    COUNT(*) AS Total,
    COUNT(Table2.Stat) AS Stat
FROM Table1
  LEFT OUTER JOIN Table2 ON (Table1.PrimaryKey = Table2.ForeignKey)
GROUP BY Table1.Category1, Table1.Category2;

Что значит:

  • Все строки из Table1 включаются в результат запроса.
  • Если в Table2 есть совпадающие строки, включите эти строки (повторение содержимого из Table1, если в Table2 есть несколько совпадающих строк).
  • Если в Table2 нет совпадающих строк, используйте NULL для всех столбцов Table2 в результате запроса.

Следует отметить, что классическая нотация Oracle не является интуитивно понятной, и ее лучше избегать с точки зрения ясности кода и удобства обслуживания.

Чтобы проиллюстрировать этот момент, я включил этот пример.

Чтобы достичь LEFT outer join между таблицами A и B, можно было бы ожидать, что таблица слева, которая является A, должна иметь рядом с собой оператор (+). Это имело бы смысл, поскольку мы хотим обозначить, что будем включать все строки A независимо от успеха в критерии соединения с B. Однако это не так, и соединение достигается следующим образом

select b.age, a.name
from Employees a, EmployeeUNI b
where a.id = b.id(+)

Я предпочитаю явную версию ANSI SQL:

select b.age, a.name
From Employees a 
    LEFT outer join EmployeeUNI b
on a.id = b.id

Оба метода приводят к одному и тому же результату, однако подход ANSI не связан с риском того, что начинающий программист ошибочно поместит (+) в неправильное место.

Другие вопросы по теме