Supongamos que queremos convertir datos de typo BYTE(2) a su valor entero. Lo primero que pensamos es en algo así como:
BTEQ -- Enter your SQL request or BTEQ command:
SELECT CAST(('327D'XB) AS INTEGER);
*** Failure 3532 Conversion between BYTE data and other types is illegal.
Statement# 1, Info =0
*** Total elapsed time was 1 second.
Error. En Teradata los typos BYTE son bastante puñeteros, y no permiten la conversión de tipos en ninguna circunstancia (Esto es una máxima en Teradata).
Entonces ¿qué hacemos si queremos convertir un valor BYTE a su entero correspondiente? Pues que deberemos, como siempre, hacer trampas.
Teradata basa su paralelismo y su necesaria distribución de los datos en unas funciones de ‘hashing‘ que son las encargadas de distribuir las filas en los AMPs basándose en los valores de las columnas definidas en los ‘primary indexes‘. Además ofrece al usuario tres funciones de utilidad para poder analizar dicha distribución: HASHROW, HASHBUCKET y HASHAMP. Normalmente se utilizan juntas, ya que la salida de una suele ser la entrada de la otra:
SELECT HASHAMP(HASHBUCKET(HASHROW('A')));
*** Query completed. One row found. One column returned.
*** Total elapsed time was 1 second.
HASHAMP(HASHBUCKET(HASHROW('A')))
---------------------------------
4
Esto quiere decir que si tuviéramos una tabla cuyo ‘primary index‘ fuese una columna CHAR(1), una fila cuyo valor para esa columna fuese ‘A’ estaría localizada en el AMP número 4 (esto depende de la configuración de cada sistema y sería algo largo explicar aquí todo el mecanismo, el que quiera puede repasarse la documentación).
Nosotros nos vamos a centrar en la segunda función “HASHBUCKET”, que recibe un BYTE(4) como resultado de la salida de “HASHROW” y devuelve un entero de cuatro bytes. Los dos primeros bytes se llaman DSW (‘destination selection word‘) y aquí viene el truco: esta DSW no es más que un valor entre 0 y 65535 que se utilizará luego en el “HASHMAP”, pero esa es otra historia…
El caso es que si tenemos un valor de hasta 2 bytes (’1A9F’, por ejemplo) podemos resolver su valor entero haciendo esto:
BTEQ -- Enter your SQL request or BTEQ command:
SELECT HASHBUCKET('1A9F0000'XB);
*** Query completed. One row found. One column returned.
*** Total elapsed time was 1 second.
HASHBUCKET('1A9F0000'XB)
------------------------
6815
Y devuelve 6815 que es, efectivamente, el valor entero de ’1A9F’.
Nótese que hemos tenido que rellenar a ceros hasta conseguir un BYTE(4), que es lo que pide HASHBUCKET(), pero nos permite un ‘CAST’ que de otra manera está prohibido.
Pero aún podemos ir un poco más lejos:
BTEQ -- Enter your SQL request or BTEQ command:
CREATE TABLE MY_DB.PRUEBA01(ID_N INTEGER NOT NULL,
B_N2 BYTE(2) NOT NULL
)
UNIQUE PRIMARY INDEX (ID_N)
;
*** Table has been created.
*** Total elapsed time was 1 second.
BTEQ -- Enter your SQL request or BTEQ command:
INSERT INTO MY_DB.PRUEBA01(ID_N, B_N2) VALUES (1, '0001'XB);
*** Insert completed. One row added.
*** Total elapsed time was 1 second.
BTEQ -- Enter your SQL request or BTEQ command:
INSERT INTO MY_DB.PRUEBA01(ID_N, B_N2) VALUES (2, '0002'XB);
*** Insert completed. One row added.
*** Total elapsed time was 1 second.
BTEQ -- Enter your SQL request or BTEQ command:
INSERT INTO MY_DB.PRUEBA01(ID_N, B_N2) VALUES (10, '000A'XB);
*** Insert completed. One row added.
*** Total elapsed time was 1 second.
BTEQ -- Enter your SQL request or BTEQ command:
INSERT INTO MY_DB.PRUEBA01(ID_N, B_N2) VALUES (255, '00FF'XB);
*** Insert completed. One row added.
*** Total elapsed time was 1 second.
BTEQ -- Enter your SQL request or BTEQ command:
INSERT INTO MY_DB.PRUEBA01(ID_N, B_N2) VALUES (65535, 'FFFF'XB);
*** Insert completed. One row added.
*** Total elapsed time was 1 second.
BTEQ -- Enter your SQL request or BTEQ command:
SELECT * FROM MY_DB.PRUEBA01 ORDER BY 1
;
*** Query completed. 5 rows found. 2 columns returned.
*** Total elapsed time was 1 second.
ID_N B_N2
----------- ----
1 0001
2 0002
10 000A
255 00FF
65535 FFFF
Tenemos una tabla con valores BYTE(2) y sus enteros correspondientes (sólo a efectos de demostración).
Podemos entonces convertir los BYTE(2) a enteros entre 0 y 65535 haciendo:
BTEQ -- Enter your SQL request or BTEQ command:
SELECT ID_N, B_N2, HASHBUCKET(B_N2||'0000'XB)
FROM MY_DB.PRUEBA01
ORDER BY 1;
*** Query completed. 5 rows found. 3 columns returned.
*** Total elapsed time was 1 second.
ID_N B_N2 HASHBUCKET((B_N2||'0000'XB))
----------- ---- ----------------------------
1 0001 1
2 0002 2
10 000A 10
255 00FF 255
65535 FFFF 65535
et voilà! Aprovechando que podemos ‘concatenar bytes’ utilizando la expresión “||’0000′XB”, conseguimos rellenar a ceros los dos bytes restantes que espera “HASHBUCKET” y realizar la conversión prohibida.
Saludos.
Carlos.
[...] viendo claro. Sólamente con conocer como funciona SUBSTR() con datos tipo ‘BYTE’ y cómo convertir estos datos a ‘INTEGERs’ podemos hacer la [...]