tables - sql join shorthand




L'ambiguità nella sinistra si unisce(solo oracolo?) (8)

Ecco la query (versione semplificata)

Penso che semplificando la query hai rimosso la vera causa del bug :-)

Quale versione di oracle stai usando? Oracle 10g (10.2.0.1.0) fornisce:

create table parts (ptno number , ptnm number , catcd number);  
create table CATEGORIES (catcd number);

select PTNO,PTNM,CATCD from PARTS  
left join CATEGORIES on (CATEGORIES.CATCD=PARTS.CATCD);

Ottengo ORA-00918: colonna definita ambiguamente

Il mio capo ha trovato un bug in una query che ho creato e non capisco il ragionamento dietro il bug, sebbene i risultati della query dimostrino che è corretto. Ecco la query (versione semplificata) prima della correzione:

select PTNO,PTNM,CATCD
from PARTS 
left join CATEGORIES on (CATEGORIES.CATCD=PARTS.CATCD); 

e qui è dopo la correzione:

select PTNO,PTNM,PARTS.CATCD
from PARTS 
left join CATEGORIES on (CATEGORIES.CATCD=PARTS.CATCD); 

Il bug era che i valori nulli venivano mostrati per la colonna CATCD, cioè i risultati della query includevano i risultati delle CATEGORIE della tabella invece delle PARTI. Ecco cosa non capisco: se c'era una certa ambiguità nella query originale, perché Oracle non ha lanciato un errore? Per quanto ho capito, nel caso dei join di sinistra, la tabella "principale" nella query (PARTI) ha la precedenza nell'ambiguità. Ho sbagliato, o semplicemente non sto pensando a questo problema correttamente?

Aggiornare:

Ecco un esempio rivisto, in cui non viene generato l'errore di ambiguità:

CREATE TABLE PARTS (PTNO NUMBER, CATCD NUMBER, SECCD NUMBER);

CREATE TABLE CATEGORIES(CATCD NUMBER);

CREATE TABLE SECTIONS(SECCD NUMBER, CATCD NUMBER);


select PTNO,CATCD 
from PARTS 
left join CATEGORIES on (CATEGORIES.CATCD=PARTS.CATCD) 
left join SECTIONS on (SECTIONS.SECCD=PARTS.SECCD) ;

Qualcuno ha un indizio?


@Pat: ottengo lo stesso errore qui per la tua query. La mia query è solo un po 'più complicata di quella che ho originariamente pubblicato. Sto lavorando ad un semplice esempio riproducibile ora.


Dalla mia esperienza, se crei una query come questa, il risultato dei dati attirerà CATCD dal lato destro del join non a sinistra quando c'è un sovrapposizione di campi come questo.

Quindi, poiché questo join avrà tutti i record di PARTS con solo un passaggio da CATEGORIES avrai NULL nel campo CATCD ogni volta che non ci sono dati sul lato destro.

Definendo esplicitamente la colonna come da PARTI (cioè lato sinistro) si otterrà un valore non nullo assumendo che il campo contenga dati in PARTI.

Ricorda che con LEFT JOIN hai solo dati garantiti nei campi dalla tabella di sinistra, potrebbero esserci colonne vuote a destra.


In genere si consiglia di essere specifici e di qualificare completamente tutti i nomi di colonne, poiché salva l'ottimizzatore un po 'di lavoro. Sicuramente in SQL Server.

Da quello che posso leggere dai documenti Oracle , sembra che verrà lanciato solo se si seleziona il nome della colonna due volte nell'elenco di selezione, o una volta nell'elenco di selezione e poi di nuovo altrove come una clausola order by.

Forse hai scoperto una 'caratteristica non documentata' :)


Questo è un bug in Oracle 9i. Se si uniscono più di 2 tabelle usando la notazione ANSI, non rileverà le ambiguità nei nomi delle colonne e può restituire la colonna sbagliata se non si utilizza un alias.

Come già detto, è fissato in 10g, quindi se non viene usato un alias, verrà restituito un errore.


Questo potrebbe essere un bug nell'ottimizzatore Oracle. Posso riprodurre lo stesso comportamento sulla query con 3 tabelle. Intuitivamente sembra che dovrebbe produrre un errore. Se lo riscrivo in uno dei seguenti modi, genera un errore:

(1) Uso della giuntura esterna vecchio stile

select ptno, catcd
from parts, categories, sections
where categories.catcd (+) = parts.catcd
  and sections.seccd (+) = parts.seccd

(2) Isolamento esplicito dei due join

select ptno, catcd
from (
  select ptno, seccd, catcd
  from parts
  left join categories on (categories.CATCD=parts.CATCD) 
)
left join sections on (sections.SECCD=parts.SECCD)

Ho usato DBMS_XPLAN per ottenere dettagli sull'esecuzione della query, che ha mostrato qualcosa di interessante. Il piano consiste essenzialmente nell'unire parti esterne e categorie, proiettare il set di risultati, quindi aggiungerlo all'esterno a SECTIONS. La parte interessante è che nella proiezione del primo join esterno, è incluso solo PTNO e SECCD - NON include il CATCD da nessuna delle prime due tabelle. Quindi il risultato finale è ottenere CATCD dal terzo tavolo.

Ma non so se questa sia una causa o un effetto.


Sto usando Oracle 9.2.0.8.0. e dà l'errore "ORA-00918: colonna ambiguamente definita".


Temo di non poterti dire perché non ricevi un'eccezione, ma posso postulare sul motivo per cui ha scelto la versione di CATEGORIES della colonna sulla versione di PARTS.

Per quanto ho capito, nel caso dei join di sinistra, la tabella "principale" nella query (PARTI) ha la precedenza nell'ambiguità

Non è chiaro se per "principale" intendi semplicemente la tabella di sinistra in un join di sinistra, o la tabella di "guida", come vedi concettualmente la query ... Ma in entrambi i casi, ciò che vedi come la tabella "principale" in la query così come l'hai scritta non sarà necessariamente la tabella "principale" nell'esecuzione effettiva di quella query.

La mia ipotesi è che Oracle stia semplicemente usando la colonna dalla prima tabella che colpisce nell'esecuzione della query. E poiché la maggior parte delle singole operazioni in SQL non richiedono che una tabella venga colpita prima dell'altro, il DBMS deciderà in fase di analisi che è la più efficiente da analizzare per prima. Prova a ottenere un piano di esecuzione per la query. Sospetto che possa rivelare che sta colpendo prima CATEGORIE e poi PARTI.





join