Still Up & Right

14 marzo \14\UTC 2014

El nuevo ‘magic quadrant’ de Gartner de marzo de 2014 sigue considerando a Teradata líder de los Data Warehouse DBMS’s.

Gartner Magic Quadrant March 2014

Gartner Magic Quadrant March 2014

Saludos.

Carlos.


Teradata Certified Professional (otra vez)

16 febrero \16\UTC 2014

Desde esta semana soy “Teradata 14 Certified Professional” además de “Teradata 12 Certified Professional”, que ya era.

¿Que para qué sirve? Pues no estoy muy seguro…

Saludos.

Carlos.


FORMAT… ¿UNFORMAT?

23 noviembre \23\UTC 2013

FORMAT es una cláusula que Teradata utiliza para formatear resultados de ‘queries’. Es análoga a las conocidas funciones de Oracle (y desde la versión 14 también en Teradata) TO_CHAR(), TO_DATE(), TO_NUMBER()… pero la principal diferencia es que FORMAT se puede utilizar en sentencias ‘DDL’ (Data Definition Language). Esto es: la forma en que los datos se presentarán se guarda en la propia definición de la tabla en el diccionario de datos de Teradata.
Hay que tener en cuenta que FORMAT sólo hace eso: actuar sobre la presentación de los datos, pero no modifica en modo alguno el tipo de dato ni la forma en la que éste se almacena.

 BTEQ -- Enter your SQL request or BTEQ command:
CREATE TABLE CARLOS.PRUEBA01
   ( ID_N INTEGER NOT NULL,
     C_TXT VARCHAR(25) FORMAT 'X(10)'
   )
   UNIQUE PRIMARY INDEX (ID_N)
;

 *** Table has been created.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your SQL request or BTEQ command:
SHOW TABLE CARLOS.PRUEBA01;

 *** Text of DDL statement returned.
 *** Total elapsed time was 1 second.

--------------------------------------------------------------------------------
CREATE SET TABLE CARLOS.PRUEBA01 ,NO FALLBACK ,
     NO BEFORE JOURNAL,
     NO AFTER JOURNAL,
     CHECKSUM = DEFAULT,
     DEFAULT MERGEBLOCKRATIO
     (
      ID_N INTEGER NOT NULL,
      C_TXT VARCHAR(25) CHARACTER SET LATIN NOT CASESPECIFIC FORMAT 'X(10)')
UNIQUE PRIMARY INDEX ( ID_N );

 BTEQ -- Enter your SQL request or BTEQ command:
INSERT INTO CARLOS.PRUEBA01
VALUES(1, '1234567890123456789012345');

 *** Insert completed. One row added.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your SQL request or BTEQ command:
SELECT * FROM CARLOS.PRUEBA01;

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

       ID_N  C_TXT
-----------  ----------
          1  1234567890

En el caso anterior sólo se muestran los primeros 10 caracteres de las cadenas VARCHAR(25) (aunque las cadenas sí existirán completas en la tabla y se podrían mostrar con otra cláusula FORMAT en el SELECT que las consulte, que tendrá precedencia sobre el FORMAT de la definición de la tabla)

 BTEQ -- Enter your SQL request or BTEQ command:
SELECT ID_N, C_TXT (FORMAT 'X(25)') FROM CARLOS.PRUEBA01;

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

       ID_N  C_TXT
-----------  -------------------------
          1  1234567890123456789012345

Podemos cambiar el formato de la columna con un ALTER TABLE … ADD … FORMAT:

 BTEQ -- Enter your SQL request or BTEQ command:
ALTER TABLE CARLOS.PRUEBA01 ADD C_TXT FORMAT 'X(30)';

 *** Table has been modified.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your SQL request or BTEQ command:
SHOW TABLE CARLOS.PRUEBA01;

 *** Text of DDL statement returned.
 *** Total elapsed time was 1 second.

--------------------------------------------------------------------------------
CREATE SET TABLE CARLOS.PRUEBA01 ,NO FALLBACK ,
     NO BEFORE JOURNAL,
     NO AFTER JOURNAL,
     CHECKSUM = DEFAULT,
     DEFAULT MERGEBLOCKRATIO
     (
      ID_N INTEGER NOT NULL,
      C_TXT VARCHAR(25) CHARACTER SET LATIN NOT CASESPECIFIC FORMAT 'X(30)')
UNIQUE PRIMARY INDEX ( ID_N );

En ese caso, las cadenas VARCHAR(25) serán rellenadas por la derecha (‘padded’) hasta su formato de 30 caracteres.

Pero, ¿qué pasa si queremos eliminar el formato de una columna? No existe una cláusula “UNFORMAT”…

Lo primero es intentar un ALTER TABLE … ADD … sin FORMAT:

 BTEQ -- Enter your SQL request or BTEQ command:
ALTER TABLE CARLOS.PRUEBA01 ADD C_TXT VARCHAR(25);

 *** Table has been modified.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your SQL request or BTEQ command:
SHOW TABLE CARLOS.PRUEBA01;

 *** Text of DDL statement returned.
 *** Total elapsed time was 1 second.

--------------------------------------------------------------------------------
CREATE SET TABLE CARLOS.PRUEBA01 ,NO FALLBACK ,
     NO BEFORE JOURNAL,
     NO AFTER JOURNAL,
     CHECKSUM = DEFAULT,
     DEFAULT MERGEBLOCKRATIO
     (
      ID_N INTEGER NOT NULL,
      C_TXT VARCHAR(25) CHARACTER SET LATIN NOT CASESPECIFIC FORMAT 'X(30)')
UNIQUE PRIMARY INDEX ( ID_N );

Pero vemos que no funciona: no hemos conseguido nada.

Discurriendo (y antes de crear otra tabla sin el FORMAT y hacer un INSERT… SELECT para luego borrar la tabla original y renombrar la nueva) podíamos probar a modificar la columna a su formato ‘por defecto':

 BTEQ -- Enter your SQL request or BTEQ command:
ALTER TABLE CARLOS.PRUEBA01 ADD C_TXT FORMAT 'X(25)';

 *** Table has been modified.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your SQL request or BTEQ command:
SHOW TABLE CARLOS.PRUEBA01;

 *** Text of DDL statement returned.
 *** Total elapsed time was 1 second.

--------------------------------------------------------------------------------
CREATE SET TABLE CARLOS.PRUEBA01 ,NO FALLBACK ,
     NO BEFORE JOURNAL,
     NO AFTER JOURNAL,
     CHECKSUM = DEFAULT,
     DEFAULT MERGEBLOCKRATIO
     (
      ID_N INTEGER NOT NULL,
      C_TXT VARCHAR(25) CHARACTER SET LATIN NOT CASESPECIFIC)
UNIQUE PRIMARY INDEX ( ID_N );

 BTEQ -- Enter your SQL request or BTEQ command:

Y sí: mágicamente, la cláusula FORMAT ha desaparecido del DDL de la tabla almacenado en el diccionario de datos.

Así pues, para eliminar una cláusula FORMAT no deseada en la definición de una tabla basta con redefinir la(s) columna(s) con su FORMAT ‘por defecto’.

Saludos.

Carlos.


Teradata Wallet

14 agosto \14\UTC 2013

Teradata Wallet es una herramienta cliente bastante rupestre que sirve para poder hacer conexiones a Teradata en ‘scripts‘ (bteq, fatsload, multiload, arcmain… todos sobre CLIV2) de forma que no haya que tener las contraseñas escritas ‘en claro’ en las conexiones de dichos ‘scripts‘.

Apareció hará un par de años, y el principal problema era que no había ninguna documentación sobre cómo utilizarla. Con el tiempo han ido apareciendo algunos artículos y con esto y con el habitual ensayo-error he conseguido entender un poco cómo funciona.

Teradata Wallet no es más que un contenedor de pares atributo-valor en los cuales el valor se almacena cifrado y se invoca mediante (el nombre de) su atributo. Así se consigue evitar la codificación de las contraseñas en los ‘scripts‘ (‘hardcoded passwords‘). Cada usuario de un sistema tendrá su propio ‘wallet‘ (billetera) con sus atributos-valores que pueden ser invocados mediante llamadas simples a la herramienta en la forma “$tdwallet(atributo)”.

La instalación es un “rpm” que se instala con un simple “rpm -ivh”. No obstante, hay que tener en cuenta un par de cosas:

  • Teradata Wallet debe ser instalado con la misma versión de las TTU’s existentes. Si, por ejemplo, instalamos un Teradata Wallet 14.10 sobre una instalación de TTU’s 14.0 las conexiones a Teradata fallarán con “*** Failure 8017 The UserId, Password or Account is invalid.”
  • El rpm debe ser instalado como ‘root‘.

Vamos a ver un ejemplo de cómo funciona.

Supongamos que tenemos un ‘script’ bteq que en su primera línea realiza una conexión al Teradata local haciendo “.LOGON localhost/carlos,micontraseña”

Mediante la creación de un par tributo-valor en el Teradata Wallet podemos evitar tener que poner la contraseña en claro en la conexión:

carlos@TDExpress1403_Sles10:~> tdwallet add password_local
Enter desired value for the string named "password_local":
String named "password_local" added.

Sustituímos en el ‘script’ la contraseña por una llamada a tdwallet con el nuevo atributo creado:

carlos@TDExpress1403_Sles10:~> cat prueba.btq
.LOGON localhost/carlos,$tdwallet(password_local)
SELECT DATE;
.LOGOFF;
carlos@TDExpress1403_Sles10:~>

Y ya sólo queda probarlo:

carlos@TDExpress1403_Sles10:~> bteq < prueba.btq
BTEQ 14.00.00.05 Wed Aug 14 11:59:02 2013

+---------+---------+---------+---------+---------+---------+---------+----
.LOGON localhost/carlos,

 *** Logon successfully completed.
 *** Teradata Database Release is 14.00.03.02
 *** Teradata Database Version is 14.00.03.02
 *** Transaction Semantics are BTET.
 *** Session Character Set Name is 'ASCII'.

 *** Total elapsed time was 1 second.

+---------+---------+---------+---------+---------+---------+---------+----
SELECT DATE;

 *** Query completed. One row found. One column returned.
 *** Total elapsed time was 2 seconds.

    Date
--------
13/08/14

+---------+---------+---------+---------+---------+---------+---------+----
.LOGOFF;
 *** You are now logged off from the DBC.
+---------+---------+---------+---------+---------+---------+---------+----
 *** Warning: EOF on INPUT stream.
 *** BTEQ exiting due to EOF on stdin.

 *** Exiting BTEQ...
 *** RC (return code) = 0

Para Teradata la conexión no ha cambiado, pues recibe la contraseña de la misma manera que antes. La diferencia es que ahora no hace falta que esté en el ‘script’.

Teradata Wallet no sólo vale para almacenar contraseñas, también puede almacenar usuarios o cualquier otra información que se necesite. Cuando la herramienta trata el ‘script‘ las llamadas a $tdwallet(atributo) se expanden de la misma manera que ocurre con las variables en los ‘scripts‘ de ‘bash‘. Así pues, se podrían distribuir ‘scripts‘ idénticos a usuarios distintos con llamadas que el ‘wallet‘ de cada usuario resolvería de forma independiente. P. ej.: “.LOGON $tdwallet(tdsystem)/$tdwallet(tduser),$tdwallet(tdpassword)”

Saludos.

Carlos.


Verificar ficheros ‘VARTEXT’ (awk is your friend II).

8 agosto \08\UTC 2013

Una de las formas frecuentes de cargar datos en Teradata (con fastload, multiload, bteq…) es a partir de ficheros de texto de longitud variable con un carácter separador de campos. Estos ficheros deben tener una estructura de campos coherente con la definición que hagamos en la herramienta de carga ( ‘DEFINE’ en fastload, ‘LAYOUT’ en multiload,’USING’ en bteq …). Pero a menudo ocurre que los ficheros son grandes y no es muy cómodo descubrir cuáles de sus filas no cumplen con las longitudes máximas de cada uno de los campos.

Aquí es donde awk puede ayudarnos de una forma rápida y simple.

Supongamos que tenemos un fichero cuyos registros deben cumplir una estructuta tipo ‘VARTEXT’ definida:

COL1  VARCHAR(7)
COL2  VARCHAR(110)
COL3  VARCHAR(120)
COL4  VARCHAR(44)
COL5  VARCHAR(9)
COL6  VARCHAR(15)
COL7  VARCHAR(6)
COL8  VARCHAR(5)
COL9  VARCHAR(8)
COL10 VARCHAR(3)

y que cuyo separador de campos es el ‘pipe’ (‘|’).

Para ver qué filas incumplen la estructura y nos darán problemas a la hora de cargarlas con la herramienta elegida (fastload, multiload, bteq…) podemos hacer simplemente:

awk 'BEGIN {FS = "|"}
        { v_rownumber+=1
                         if ( length($1)  >   7 ||
                              length($2)  > 110 ||
                              length($3)  > 120 ||
                              length($4)  >  44 ||
                              length($5)  >   9 ||
                              length($6)  >  15 ||
                              length($7)  >   6 ||
                              length($8)  >   5 ||
                              length($9)  >   8 ||
                              length($10) >   3 ) 
                            { v_errnumber+=1
                              printf "La fila %i tiene formato erróneo:%s\n", v_rownumber, $0
                            }
        }
     END { printf "Se han encontrado %i líneas erróneas de un total de %i leídas.\n", v_errnumber, v_rownumber }
    ' ruta/fichero_vartext_a_cargar.txt

La salida del proceso nos mostrará todas las filas que desborden el tamaño de cualquiera de los campos definidos. Con un poco más de código, también se puede hacer que además muestre qué campos son los que fallan.

Saludos.

Carlos.


Oracle Temporal Validity.

3 julio \03\UTC 2013

Una de las nuevas funcionalidades incluidas en el nuevo Oracle 12c es la llamada ‘Oracle Temporal Validity‘. Esta nueva característica añade una dimensión temporal a la información contenida en las tablas (“desde cuándo y hasta cuándo la información de la fila es válida“).

Este tratamiento temporal se implementa utilizando la nueva cláusula ‘add period for valid_time‘ (‘valid_time’ u otro nombre que queramos dar), que crea dos columnas ocultas de principio y fin de vigencia del dato y que se pueden utilizar de manera ‘transparente’ con un nuevo predicado en el ‘WHERE': ‘as of period for valid_time <cuándo>’, lo que mostrará los datos tal y como se verían en el momento especificado (suena muy moderno pero, en el fondo, no deja de ser un ‘BETWEEN’).

Una funcionalidad que parece querer remedar la original Teradata Temporal disponible en Teradata desde la versión 13.10.

Saludos.

Carlos.


Doing it all again…

1 julio \01\UTC 2013

Me he tomado mi tiempo y, como dijimos aquí, me he bajado la nueva versión de la Teradata Express for VMware (v.14.00.03.02) y la he configurado (de nuevo).

Un par de cosas que he hecho y que quizá sean de utilidad:

He cambiado el ‘display manager‘ a gdm, que me gusta más.

He creado lanzadores (‘launchers‘) en el escritorio de mi usuario (‘carlos’) para poder arrancar, parar y ver el estado de Viewpoint (ya que estos lanzadores sólo existen en el escritorio de ‘root‘). Esta VM permite arrancar y parar viewpoint manualmente desde el principio, sin necesidad de tener que hacer todo lo que hice aquí.

El resultado:

Teradata Express 14.0.3

Teradata Express 14.0.3

Por supuesto, toda la configuración de red (NAT), ‘proxy’, ‘gateway’ y demás, ha habido que hacerla también de nuevo.

Saludos.

Carlos.


Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 44 seguidores