Son aquellas pequeñas cosas…

Y, claro, esta entrada tampoco tiene nada que ver con la canción de Serrat.

Es acerca de un ‘mail’ que me ha llegado recientemente:

Carlos, soy un lector “esporádico” de tu blog y por estos tiempos me encuentro
desarrollando en Teradata luego de haber pasado muchos años con Oracle. No deja
de sorprenderme (como a muchos otros) la cantidad de “pequeños detalles” que
hacen diferentes a ambas bases de datos en cuanto a sintaxis y resultados. Por
ejemplo,
La sentencia en ORA :

SELECT
 CASE
   WHEN '' = 0 THEN 'A'
   ELSE 'B'
 END
FROM DUAL

Arroja como resultado ‘B’ (como era de esperar).

Hete aquí que en ejecutando desde el Assistant en Teradata el resultado es otro: ‘A’
¿Por qué? ¿Algún “casteo” implícito de utilitario? Si me pudieras dar una respuesta te lo agradecería.

Saludos,

En efecto,esta es una de ‘aquellas pequeñas cosas’ que a veces se nos pueden llegar a atragantar al pasar de un RDBMS a otro. Y sí, algo tiene que ver con el ‘cast‘, pero no sólo con eso.

Vamos primero con el Oracle:

La razón aquí es la pura y simple lógica trivaluada (TRUE, FALSE, NULL) y de que para Oracle una cadena vacía (”) es NULL. Ojo a esto, porque es una particularidad de Oracle.

Así pues, lo que está ocurriendo es que la comparación realizada es 0=NULL?=>NULL, con lo que el CASE devuelve el ELSE (‘B’).

Pero en Teradata las cosas no son así. Primero, la cadena vacía no es un NULL:

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT TYPE('');

 *** Query completed. One row found. One column returned.
 *** Total elapsed time was 1 second.

Type('')
---------------------------------------
VARCHAR(0) CHARACTER SET UNICODE

 BTEQ -- Enter your DBC/SQL request or BTEQ command:

SELECT 1 WHERE '' IS NULL;

 *** Query completed. No rows found.
 *** Total elapsed time was 1 second.

Como se demuestra aquí, para Teradata la cadena vacía es de tipo VARCHAR(0) y no es NULL.

Pues ya sólo queda saber por qué para Teradata la cadena vacía (”) es igual a cero. Y ahí sí que entra el juego el ‘casting‘ o, más concretamente, las conversiones implícitas.

Esto lo aclara la documentación oficial de Teradata: ‘SQL Functions, Operators, Expressions, and Predicates‘, capítulo 4: ‘Comparison Operators. Implicit Type Conversion of Comparison Operands‘:

Data Types on Which Implicit Conversion is Performed
If operand data types differ, then Teradata Database performs an implicit conversion according to the following table. Implicit conversions are Teradata extensions to the ANSI SQL:2008 standard.

IF one expression   AND the other expression   THEN Teradata Database
operand is …        operand is …               compares the data as ...
Character           BYTEINT                    FLOAT
                    SMALLINT
                    INTEGER
                    FLOAT

Y eso es todo: Teradata convierte ” (VARCHAR(0)) a float, y el valor que asigna en la conversión es cero (0). En realidad, convertirá la cadena vacía a 0 para cualquier tipo de dato numérico :

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT CAST( '' AS FLOAT);


 *** Query completed. One row found. One column returned.
 *** Total elapsed time was 1 second.

                    ''
----------------------
 0.00000000000000E 000

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT CAST( '' AS integer);


 *** Query completed. One row found. One column returned.
 *** Total elapsed time was 1 second.

         ''
-----------
          0

Y así la comparación ” = 0 será cierta:

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT 1 WHERE '' = 0;


 *** Query completed. One row found. One column returned.
 *** Total elapsed time was 1 second.

   1
----
   1

con lo que el CASE interpreta 0=0 THEN ‘A’.

Saludos.

Carlos

Anuncios

Una respuesta a Son aquellas pequeñas cosas…

  1. Jorge dice:

    Gracias Carlos. Me fue de mucha utilidad. Ahora a seguir remandola… 😉
    Saludos.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: