2010-02-24 13 views
11

Tengo una consulta que une dos tablas. Una tabla tiene una columna que es de tipo varchar, y la otra tabla tiene un tipo de número. He ejecutado mi consulta en 3 bases de datos de Oracle, y estoy viendo algunos resultados extraños que espero se puedan explicar. En dos de las bases de datos algo así como los siguientes trabajos.número de Oracle y varchar join

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

En este tableA.col1 consulta es de tipo número y tableB.col2 es de tipo varchar. Esto funciona bien en dos de las bases de datos, pero no en el tercero. En el tercero obtengo el error (ORA-01722). En el tercero tengo que hacer algo como ...

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

Esto funciona en todas las bases de datos. La pregunta que tengo es por qué? Lo anterior es una consulta simplificada, y la consulta real es un poco más compleja y recupera una gran cantidad de datos, por lo tanto, la primera versión es mucho más rápida. Si pudiera hacer que funcione en todos los entornos, sería genial.

¿Alguien sabe por qué esto puede funcionar en algunas bases de datos de Oracle y no en otras sin el molde en el tipo de datos? ¿Existe una configuración global que permita dicho comportamiento?

+1

colación sería mi primera conjetura. Oracle generalmente permite la conversión implícita, por lo que podría ser que una columna no pase la conversión implícita ... –

+1

Escribiste todas esas palabras y aún no lograste explicar con precisión * cómo * la primera consulta no funciona en el tercera base de datos. – APC

+0

Lo siento, recibo un error ORA-01722 en la primera consulta, tercera base de datos – broschb

Respuesta

15

Una razón por la que las conversiones implícitas fallan es cuando la columna varchar que une contiene datos que no son numéricos. Oracle maneja número a varchar2 se une mediante la conversión de las cadenas (echa un vistazo a la citación de Gary en su comentario), por lo que realmente ejecuta esto:

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

Si tableB.col2 contiene valores que no son numéricos - parece bastante probable, es una cadena, después de todo, lanzará ORA-01722: invalid number. Al emitir explícitamente la columna de número a una cadena, cortocircuita el comportamiento predeterminado de Oracle.

El hecho de que no se presente este problema en sus dos primeros entornos es una cuestión de suerte, no de configuración. Podría aparecer en cualquier momento, ya que solo requiere una cadena no numérica para romper la consulta. Entonces, realmente debe ejecutar con la conversión explícita en todos los entornos.

En cuanto a rendimiento, se podría construir un índice basado en las funciones ...

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

Un poco después de http://download.oracle.com/docs/cd/B19306_01/server.102/b14200 /sql_elements002.htm#r16c1-t41 "Al comparar un valor de carácter con un valor numérico, Oracle convierte los datos del carácter en un valor numérico". –

+0

Puede convertir el número en la tabla A en una cadena en su lugar, de modo que no obtendrá errores si hay una cadena no numérica en la tabla B. es decir, CAST (a.col1 AS VARCHAR (20)) –