2012-03-27 10 views
7

Ho trovato questo strano comportamento e mi sto rompendo il cervello con questo ... qualcuno ha qualche idea?Seleziona stringa come numero su Oracle

Oracle 10g: Ho due tabelle diverse, entrambi hanno questa colonna denominata "TESTCOL", come Varchar2 (10), non annullabile.

Se eseguo questa ricerca table1, ottengo i risultati corretti:

select * from table1 where TESTCOL = 1234; 

Nota che non sto mettendo in particolare '1234' ... non è un errore di battitura, che è un query generate dinamicamente e cercherò di non cambiarlo (almeno non nel prossimo futuro).

Ma, se esegue la stessa query, il table2, ricevo questo messaggio di errore:

ORA-01722: Invalid number 

Entrambe le query vengono eseguite sulla stessa sessione, stesso database.

Mi sono unito a queste due tabelle da quella colonna e il join funziona correttamente, l'unico problema si verifica ogni volta che provo a utilizzare quella condizione.

Qualche idea su cosa potrebbe essere diverso da un tavolo all'altro?

Grazie in anticipo.

risposta

22

Se TESTCOL contiene numeri diversi, Oracle potrebbe incorrere in problemi durante la conversione di voci TESTCOL in numeri. Perché, che cosa fa internamente, è questo:

select * from table1 where TO_NUMBER(TESTCOL) = 1234; 

Se sei così sicuro che 1234 non può essere espresso come un VARCHAR letterale, quindi provare questo posto, al fine di confrontare i valori VARCHAR, piuttosto che quelli numerici:

select * from table1 where TESTCOL = TO_CHAR(1234); 
3

Si sta colpendo i pericoli impliciti di typecasting qui.

Con l'espressione testcol = 1234 si dichiara che si desidera trattare testcol come una colonna numerica, quindi Oracle tenta di convertire tutti i valori in quella colonna in un numero.

L'ORA-01722 si verifica perché apparentemente almeno un valore in quella colonna è non un numero.

Anche se si sostiene che questo è "non è un errore di battitura" è effettivamente uno. È un errore sintattico.

Si dovrà dichiarare il vostro parametro come una stringa utilizzando apici letterali: where testcol = '1234'

Creazione di una condizione corretta è l'unica soluzione al vostro problema.

4

Ben ovvio TABLE2.TESTCOL contiene valori che non sono numeri .Il confronto di una stringa con un valore letterale numerico genera una conversione implicita. Quindi qualsiasi valore in TESTCOL che non può essere lanciato su un numero scaglierà ORA-1722.

Non ti colpisce dove confronti le due tabelle perché stai confrontando le stringhe.

Quindi avete un paio di opzioni, di cui non vi piacerà. La risposta più ovvia è quella di pulire i dati in modo che TABLE2 non contenga caratteri non numerici. Idealmente dovresti combinare questo con la modifica della colonna in un tipo di dati numerici. Altrimenti è possibile modificare il generatore in modo da produrre codice che può essere eseguito su un modello di dati shonky. In questo caso, ciò significa avvolgere i valori letterali tra virgolette se la colonna mappata ha un tipo di dati carattere.

-1

Quanto segue dovrebbe funzionare. Basta sostituire il "tuo dove".

select * 
from table1 
where (select TO_NUMBER(TESTCOL) 
     from table2 
     where "your where") = 1234; 
Problemi correlati