Aspectos curiosos de conversiones de Timestamp con CAST() en Teradata.

Yo soy un firme defensor del uso de CAST() en Teradata (y en otros SGBDR’s) por la sencilla razón de que se trata de un comando ‘ANSI’. Teradata permite otras formas de ‘casting’ sin utilizar CAST(), aunque se trata de sintaxis propietaria. Pero vamos a ver que no todo el monte es orégano y que lo que, llevados por el sentido común, podríamos pensar como algo fácil -trivial incluso- no lo es tanto.

Teradata también presenta el tipo de dato (‘datatype‘) Timestamp, que también pertenece al estándar ANSI. Este tipo de dato tiene como argumento en su definición el número de partes fraccionarias (esto es: fracciones de segundo) siendo su ‘default’ 6. Con lo que si definimos una columna como tipo Timestamp ésta será TIMESTAMP(6), lo que significa que tendremos un dato de tiempo que almacenará año, mes, día, hora, minuto, segundo y seis posiciones de la parte fraccional de un segundo: decimas, centésimas, milésimas, diezmilésimas, cienmilésimas y millonésimas.

Uno pensaría que no hay cosa más fácil que convertir un Timestamp(6) a un Timestamp(0). El sentido común nos impulsa a utilizar un simple CAST() para ello, aunque, como dije arriba, a veces las cosas no son tan sencillas como parecen:

Digamos que tenemos una tabla con una columna de tipo Timestamp(6):

 Teradata BTEQ 08.02.03.03 for WIN32.
 Copyright 1984-2006, NCR Corporation. ALL RIGHTS RESERVED.
 Enter your logon or BTEQ command:
.LOGON MY_TERADATA/carlosal

.LOGON MY_TERADATA/carlosal
Password:

 *** Logon successfully completed.
 *** Teradata Database Release is V2R.06.02.01.18
 *** Teradata Database Version is 06.02.01.17
 *** Transaction Semantics are BTET.
 *** Character Set Name is 'ASCII'.

 *** Total elapsed time was 3 seconds.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT TYPE(MY_TIMESTAMP6_COL) FROM MY_DB.MY_TABLE SAMPLE 1;

SELECT TYPE(MY_TIMESTAMP6_COL) FROM MY_DB.MY_TABLE SAMPLE 1;

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

Type(MY_TIMESTAMP6_COL)
---------------------------------------
TIMESTAMP(6)

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

Ahí está. Una columna TIMESTAMP(6).
Vamos a convertir el dato a TIMESTAMP(0) con un simple CAST():

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT CAST(MY_TIMESTAMP6_COL AS TIMESTAMP(0)) FROM MY_DB.MY_TABLE SAMPLE 1;

SELECT CAST(MY_TIMESTAMP6_COL AS TIMESTAMP(0)) FROM MY_DB.MY_TABLE SAMPLE 1;
 *** Failure 7454 DateTime field overflow.
                Statement# 1, Info =0
 *** Total elapsed time was 1 second.

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

¿Qué os decía? Lo que aparentemente debería ser tan fácil…

Puede que sea un problema de ‘FORMAT’:

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT CAST(MY_TIMESTAMP6_COL AS TIMESTAMP(0) FORMAT 'YYYYMMDDHHMISS')
 FROM MY_DB.MY_TABLE SAMPLE 1;

SELECT CAST(MY_TIMESTAMP6_COL AS TIMESTAMP(0) FORMAT 'YYYYMMDDHHMISS')
 FROM MY_DB.MY_TABLE SAMPLE 1;
 *** Failure 7454 DateTime field overflow.
                Statement# 1, Info =0
 *** Total elapsed time was 1 second.

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

¡Pues tampoco! ¿Qué hacer? Vamos a probar un rodeo con un doble CAST(), convirtiendo a VARCHAR:

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT CAST(CAST(MY_TIMESTAMP6_COL AS VARCHAR(20)) AS TIMESTAMP(0))
 FROM MY_DB.MY_TABLE SAMPLE 1;

SELECT CAST(CAST(MY_TIMESTAMP6_COL AS VARCHAR(20)) AS TIMESTAMP(0))
 FROM MY_DB.MY_TABLE SAMPLE 1;
 *** Failure 6760 Invalid timestamp.
                Statement# 1, Info =0
 *** Total elapsed time was 1 second.

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

¡Joder! ¡Ésta sí que es buena! ¡Pero si entre dos Timestamp debería estar ‘chupao’!

Lo del doble CAST() y lo del FORMAT eran dos buenas ideas. No han funcionado por separado pero ¿y juntas?

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT CAST(CAST(MY_TIMESTAMP6_COL AS VARCHAR(14)) AS TIMESTAMP(0)
 FORMAT 'YYYYMMDDHHMISS') FROM MY_DB.MY_TABLE SAMPLE 1;

SELECT CAST(CAST(MY_TIMESTAMP6_COL AS VARCHAR(14)) AS TIMESTAMP(0)
 FORMAT 'YYYYMMDDHHMISS') FROM MY_DB.MY_TABLE SAMPLE 1;

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

MY_TIMESTAMP6_COL
--------------
20081030142011

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

¡Ahí lo tenemos! Y, como prueba: los pelos de la burra:

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT TYPE(CAST(CAST(MY_TIMESTAMP6_COL AS VARCHAR(14)) AS TIMESTAMP(0)
 FORMAT 'YYYYMMDDHHMISS')) FROM MY_DB.MY_TABLE SAMPLE 1;

SELECT TYPE(CAST(CAST(MY_TIMESTAMP6_COL AS VARCHAR(14)) AS TIMESTAMP(0)
 FORMAT 'YYYYMMDDHHMISS')) FROM MY_DB.MY_TABLE SAMPLE 1;

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

Type(MY_TIMESTAMP6_COL)
---------------------------------------
TIMESTAMP(0)

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

Un poco enrevesado, pero al menos nos deja convertir el tipo sin demasiados problemas (aunque con unos cuantos más ciclos de CPU y, por consiguiente, más tiempo para ejecutar).

Saludos.

Carlos.

3 respuestas a Aspectos curiosos de conversiones de Timestamp con CAST() en Teradata.

  1. esto funciona para castear al momento de hacer un insert into de una tabla a otra????? gracias, tu explicacion vino de pelos, wey’….😉

  2. la pregunta anterior puede ser media estupida pero pregunto xq recien me estoy iniciando en bases de datos en teradata. gracias!😀

  3. CarlosAL dice:

    Esteban:
    La única pregunta estúpida es la que se deja de hacer por vergüenza o miedo a hacer el ridículo.
    El INSERT funcionará siempre que no se pierda precisión. Si haces un INSERT SELECT desde una tabla con una columna TIMESTAMP(0) a una tabla con una columna con TIMESTAMP(6) Teradata hará un CAST implícito. Si lo intentas al revés (de un TIMESTAMP(6) a un TIMESTAMP(0), se producirá un error “5404 Datetime field overflow.”
    Saludos.
    Carlos.

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: