Operatore Oracle “(+)”


155

Sto controllando alcune vecchie dichiarazioni SQL allo scopo di documentarle e probabilmente migliorarle.

Il DBMS è Oracle

Non ho capito un'affermazione che recitasse così:

select ...
from a,b
where a.id=b.id(+)

Sono confuso riguardo (+)all'operatore e non sono riuscito a trovarlo in nessun forum ... (la ricerca di + tra virgolette non ha funzionato neanche).

Ad ogni modo, ho usato "Explain Plan" di SQLDeveloper e ho ottenuto un output che diceva HASH JOIN, RIGHT OUTER, ecc.

Ci sarebbero delle differenze se rimuovo l' (+)operatore alla fine della query? Il database deve soddisfare alcune condizioni (come avere degli indici, ecc.) Prima di (+)poter essere utilizzato? Sarebbe molto utile se tu potessi fornirmi una comprensione semplice, o alcuni buoni collegamenti in cui posso leggere al riguardo.

Grazie!


1
Non è un operatore. È solo una parte della sintassi che influenza ciò che fa JOIN.
philipxy

Risposte:


187

Questa è la notazione specifica di Oracle per un OUTER JOIN, perché il formato ANSI-89 (usando una virgola nella clausola FROM per separare i riferimenti di tabella) non ha standardizzato i join OUTER.

La query verrebbe riscritta nella sintassi ANSI-92 come:

   SELECT ...
     FROM a
LEFT JOIN b ON b.id = a.id

Questo link è abbastanza buono per spiegare la differenza tra i JOIN .


Va anche notato che, sebbene funzioni(+) , Oracle consiglia di non utilizzarlo :

Oracle consiglia di utilizzare la sintassi della FROMclausola OUTER JOINanziché l'operatore di join Oracle. Le query di join esterne che utilizzano l'operatore di join Oracle (+)sono soggette alle seguenti regole e restrizioni, che non si applicano alla sintassi della FROMclausola OUTER JOIN:


79
Completamente giusto. Per mantenere il (+) dritto nella mia testa (lato sinistro contro lato destro), mi piace pensare al (+) come "aggiungere valori NULL se non viene trovata alcuna corrispondenza". Ad esempio, "a.id = b.id (+)" significa che b.id è NULL se non vi è corrispondenza con a.id.
spiaggia,

grazie..immagino che aggiungerlo dalla clausola dovrebbe produrre lo stesso risultato !!
Kiran S,

Potresti voler avere un link alla documentazione ufficiale di Oracle: docs.oracle.com/html/A95915_01/sqopr.htm
Vargan,

27

L'operatore (+) indica un join esterno. Ciò significa che Oracle restituirà comunque i record dall'altra parte del join anche in assenza di corrispondenza. Ad esempio se aeb sono emp e dept e è possibile avere dipendenti non assegnati a un dipartimento, la seguente dichiarazione restituirà i dettagli di tutti i dipendenti indipendentemente dal fatto che siano stati assegnati o meno a un dipartimento.

select * from emp, dept where emp.dept_id=dept.dept_id(+)

Quindi, in breve, la rimozione di (+) può fare la differenza, ma potresti non accorgertene per un po 'a seconda dei tuoi dati!


25

In Oracle, (+) indica la tabella "opzionale" in JOIN. Quindi nella tua query,

SELECT a.id, b.id, a.col_2, b.col_2, ...
FROM a,b
WHERE a.id=b.id(+)

è un JOIN ESTERNO SINISTRA della tabella 'b' alla tabella 'a'. Restituirà tutti i dati della tabella 'a' senza perdere i suoi dati quando l'altro lato (tabella opzionale 'b') non ha dati.

Diagramma del join esterno sinistro

La sintassi standard moderna per la stessa query sarebbe

SELECT  a.id, b.id, a.col_2, b.col_2, ...
FROM a
LEFT JOIN b ON a.id=b.id

o con una scorciatoia per a.id=b.id(non supportato da tutti i database):

SELECT  a.id, b.id, a.col_2, b.col_2, ...
FROM a
LEFT JOIN b USING(id)

Se rimuovi (+), sarà normale query di join interno

Sintassi precedente, sia in Oracle che in altri database:

SELECT  a.id, b.id, a.col_2, b.col_2, ...
FROM a,b
WHERE a.id=b.id

Sintassi più moderna:

SELECT  a.id, b.id, a.col_2, b.col_2, ...
FROM a
INNER JOIN b ON a.id=b.id

O semplicemente:

SELECT  a.id, b.id, a.col_2, b.col_2, ...
FROM a
JOIN b ON a.id=b.id

Diagramma di Inner Join

Restituirà solo tutti i dati in cui entrambi i valori 'id' delle tabelle 'a' e 'b' sono uguali, significa parte comune.

Se vuoi trasformare la tua query in Right Join

È lo stesso di un LEFT JOIN, ma cambia quale tabella è opzionale.

Diagramma della giunzione esterna destra

Vecchia sintassi Oracle:

SELECT  a.id, b.id, a.col_2, b.col_2, ...
FROM a,b
WHERE a.id(+)=b.id

Sintassi standard moderna:

SELECT  a.id, b.id, a.col_2, b.col_2, ...
FROM a
RIGHT JOIN b ON a.id=b.id

Rif. & Aiuto:

https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:6585774577187

Join esterno sinistro usando + accedi a Oracle 11g

https://www.w3schools.com/sql/sql_join_left.asp


Le etichette dei cerchi "table1" e "table2" sono senza senso. Il significato più semplice per gli elementi del cerchio sono le righe di output. Quindi la mezzaluna sinistra contiene le righe con estensione null della tabella1 e la mezzaluna destra contiene le righe con estensione null della tabella2. Altri significati per i cerchi sono oscuri. Cosa pensi esattamente significhino i diagrammi? Perché li hai messi oltre a copiare alla cieca le presentazioni (cattive) di altre persone?
philipxy

Ora hai etichettato i cerchi a & b. I cerchi non sono file di a & b. I cerchi sinistro e destro potrebbero ragionevolmente essere etichettati come righe di un join sinistro b e un join destro b. Inoltre, non descrivi cosa sono quelle righe cerchiate in termini di input. Scopri da te quali sono le cose nei circoli. Se hai intenzione di incollare le etichette a e b sui cerchi, spiega chiaramente a parole cosa ha a che fare ogni etichetta con il suo cerchio. (Non esiste un motivo semplice per etichettarli a e b.) È bene che tu abbia etichettato correttamente le zone verdi.
philipxy

6

In pratica, il simbolo + viene posizionato direttamente nell'istruzione condizionale e sul lato della tabella opzionale (quella a cui è consentito contenere valori vuoti o nulli all'interno del condizionale).


Il (+) viene messo immediatamente a destra del nome di una colonna. Questa risposta non è chiara al riguardo. Cosa dovrebbe significare "in pratica"? (Retorico.) (E probabilmente non intendi "affermazione".)
Philipxy,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.