2010-02-24 18 views
11

Ho una query che unisce due tabelle. Una tabella ha una colonna che è di tipo varchar e l'altra tabella ha il tipo di numero. Ho eseguito la mia query su 3 database Oracle e sto vedendo alcuni strani risultati che spero possano essere spiegati. Su due dei database qualcosa come i seguenti lavori.join Oracle e varchar

select a.col1, b.somecol 
from tableA a inner join tableB b on b.col2=a.col1; 

In questa tabella di queryA.col1 è di tipo numero e tabellaB.col2 è di tipo varchar. Funziona bene in due dei database ma non nel terzo. Nel terzo errore (ORA-01722). Nel terzo ho bisogno di fare qualcosa come ...

select a.col1, b.somecol 
from tableA a inner join tableB b on b.col2=to_char(a.col1); 

Questo funziona in tutti i database. La domanda che ho è perché? Quanto sopra è una query semplificata e la query reale è un po 'più complessa e recupera molti dati, quindi la prima versione è molto più veloce. Se potessi farlo funzionare in tutti gli ambienti sarebbe fantastico.

Qualcuno sa perché questo potrebbe funzionare in alcuni database di Oracle e non in altri senza il cast sul tipo di dati? C'è un ambiente globale che consente tale comportamento?

+1

regole di confronto sarebbe la mia prima ipotesi. Oracle di solito consente la conversione implicita, quindi potrebbe essere che una colonna non passi la conversione implicita ... –

+1

Hai scritto tutte quelle parole e ancora non sei riuscito a spiegare esattamente * come * la prima query non funziona nel terzo database. – APC

+0

Mi dispiace, ottengo un errore ORA-01722 nella prima query, terzo database – broschb

risposta

15

Uno dei motivi per cui le conversioni implicite non riescono è quando la colonna varchar di join contiene dati che non sono numerici. Oracle gestisce il numero di varchar2 unisce convertendo le corde (check out la citazione di Gary nel suo commento), in modo che in realtà esegue questo:

select a.col1, b.somecol 
from tableA a inner join tableB b on to_number(b.col2)=a.col1; 

Se tableB.col2 contiene valori che non sono numerici - sembra molto probabile, è una stringa dopo tutto - allora scaglierà ORA-01722: invalid number. Colando esplicitamente la colonna del numero in una stringa, si interrompe il comportamento predefinito di Oracle.

Il fatto che non si verifichi questo problema nei primi due ambienti è una questione di fortuna, non di configurazione. Può colpire in qualsiasi momento, perché richiede solo una stringa non numerica per interrompere la query. Quindi dovresti davvero eseguire la conversione esplicita in tutti gli ambienti.

quanto riguarda le prestazioni, si potrebbe costruire un indice basato su funzioni ...

create index whatever_idx on tableA (to_char(col1)) 
/
+2

Un po 'dopo http://download.oracle.com/docs/cd/B19306_01/server.102/b14200 /sql_elements002.htm#r16c1-t41 "Quando si confronta un valore di carattere con un valore numerico, Oracle converte i dati di carattere in un valore numerico." –

+0

È possibile eseguire il cast del numero in tableA su una stringa, in modo che non si verifichino errori se nella tabellaB c'è una stringa non numerica. cioè CAST (a.col1 AS VARCHAR (20)) –

Problemi correlati