Como usar dados binários

A utilidade e a flexibilidade do tipo de dados BINARY é melhor demonstrada pelo exemplo. Este tópico fornece exemplos práticos de tarefas que envolvem o tipo de dados BINARY e seus três esquemas de codificação.

Conversão entre hexadecimal e base64

O tipo de dados BINARY pode ser usado como um passo intermediário na conversão entre cadeias de caracteres hexadecimais e base64.

Converta de hexadecimal para base64 usando TO_CHAR:

SELECT c1, TO_CHAR(TO_BINARY(c1, 'hex'), 'base64') FROM hex_strings;
Copy
+----------------------+-----------------------------------------+
| C1                   | TO_CHAR(TO_BINARY(C1, 'HEX'), 'BASE64') |
|----------------------+-----------------------------------------|
| df32ede209ed5a4e3c25 | 3zLt4gntWk48JQ==                        |
| AB4F3C421B           | q088Qhs=                                |
| 9324df2ecc54         | kyTfLsxU                                |
+----------------------+-----------------------------------------+

Converta de base64 em hexadecimal:

SELECT c1, TO_CHAR(TO_BINARY(c1, 'base64'), 'hex') FROM base64_strings;
Copy
+------------------+-----------------------------------------+
| C1               | TO_CHAR(TO_BINARY(C1, 'BASE64'), 'HEX') |
|------------------+-----------------------------------------|
| 3zLt4gntWk48JQ== | DF32EDE209ED5A4E3C25                    |
| q088Qhs=         | AB4F3C421B                              |
| kyTfLsxU         | 9324DF2ECC54                            |
+------------------+-----------------------------------------+

Conversão entre texto e bytes UTF-8

As cadeias de caracteres do Snowflake são compostas por caracteres Unicode, enquanto os valores binários são compostos por bytes. Ao converter uma cadeia de caracteres em um valor binário com o formato UTF-8, é possível manipular diretamente os bytes que compõem os caracteres Unicode.

Converta cadeias de caracteres com um único caractere em sua representação UTF-8 em bytes usando TO_BINARY:

SELECT c1, TO_BINARY(c1, 'utf-8') FROM characters;
Copy
+----+------------------------+
| C1 | TO_BINARY(C1, 'UTF-8') |
|----+------------------------|
| a  | 61                     |
| é  | C3A9                   |
| ❄  | E29D84                 |
| π  | CF80                   |
+----+------------------------+

Converta uma sequência de bytes UTF-8 em uma cadeia de caracteres usando TO_CHAR , TO_VARCHAR:

SELECT TO_CHAR(X'41424320E29D84', 'utf-8');
Copy
+-------------------------------------+
| TO_CHAR(X'41424320E29D84', 'UTF-8') |
|-------------------------------------|
| ABC ❄                               |
+-------------------------------------+

Como obter o resumo MD5 em base64

Converta o resumo MD5 binário em uma cadeia de caracteres base64 usando TO_CHAR:

SELECT TO_CHAR(MD5_BINARY(c1), 'base64') FROM variants;
Copy
+----------+-----------------------------------+
| C1       | TO_CHAR(MD5_BINARY(C1), 'BASE64') |
|----------+-----------------------------------|
| 3        | 7MvIfktc4v4oMI/Z8qe68w==          |
| 45       | bINJzHJgrmLjsTloMag5jw==          |
| "abcdef" | 6AtQFwmJUPxYqtg8jBSXjg==          |
| "côté"   | H6G3w1nEJsUY4Do1BFp2tw==          |
+----------+-----------------------------------+

Conversão de binário com formato variável

Converta cadeias de caracteres em valores binários usando um formato binário extraído da cadeia de caracteres. A instrução inclui as funções TRY_TO_BINARY e SPLIT_PART:

SELECT c1,
       TRY_TO_BINARY(SPLIT_PART(c1, ':', 2), SPLIT_PART(c1, ':', 1)) AS binary_value
  FROM strings;
Copy
+-------------------------+----------------------+
| C1                      | BINARY_VALUE         |
|-------------------------+----------------------|
| hex:AB4F3C421B          | AB4F3C421B           |
| base64:c25vd2ZsYWtlCg== | 736E6F77666C616B650A |
| utf8:côté               | 63C3B474C3A9         |
| ???:abc                 | NULL                 |
+-------------------------+----------------------+

Experimente vários formatos para a conversão:

SELECT c1,
       COALESCE(
         x'00' || TRY_TO_BINARY(c1, 'hex'),
         x'01' || TRY_TO_BINARY(c1, 'base64'),
         x'02' || TRY_TO_BINARY(c1, 'utf-8')) AS binary_value
  FROM strings;
Copy
+------------------+------------------------+
| C1               | BINARY_VALUE           |
|------------------+------------------------|
| ab4f3c421b       | 00AB4F3C421B           |
| c25vd2ZsYWtlCg== | 01736E6F77666C616B650A |
| côté             | 0263C3B474C3A9         |
| 1100             | 001100                 |
+------------------+------------------------+

Nota

Como as consultas acima usam TRY_TO_BINARY, o resultado será NULL se o formato não for reconhecido ou se a cadeia de caracteres não puder ser analisada com o formato fornecido.

Converta os resultados do exemplo anterior de volta para cadeias de caracteres usando SUBSTR e DECODE:

SELECT c1,
       TO_CHAR(
       SUBSTR(c1, 2),
       DECODE(SUBSTR(c1, 1, 1), x'00', 'hex', x'01', 'base64', x'02', 'utf-8')) AS string_value
  FROM bin;
Copy
+------------------------+------------------+
| C1                     | STRING_VALUE     |
|------------------------+------------------|
| 00AB4F3C421B           | AB4F3C421B       |
| 01736E6F77666C616B650A | c25vd2ZsYWtlCg== |
| 0263C3B474C3A9         | côté             |
| 001100                 | 1100             |
+------------------------+------------------+

Decodificação personalizada com JavaScript UDF

O tipo de dados BINARY permite o armazenamento de dados arbitrários. Como JavaScript UDFs suportam o tipo de dados via Uint8Array (consulte Introdução a UDFs de JavaScript), é possível implementar uma lógica de decodificação personalizada em JavaScript. Essa não é a maneira mais eficiente de trabalhar, mas é muito poderosa.

Crie uma função que decodifique com base no primeiro byte:

CREATE OR REPLACE FUNCTION my_decoder (b BINARY)
  RETURNS VARIANT
  LANGUAGE JAVASCRIPT
AS '
  IF (B[0] == 0) {
      var number = 0;
      FOR (var i = 1; i < B.length; i++) {
          number = number * 256 + B[i];
      }
      RETURN number;
  }
  IF (B[0] == 1) {
      var str = "";
      FOR (var i = 1; i < B.length; i++) {
          str += String.fromCharCode(B[i]);
      }
      RETURN str;
  }
  RETURN NULL;';
Copy
SELECT c1, my_decoder(c1) FROM bin;
Copy
+----------------+----------------+
| C1             | MY_DECODER(C1) |
|----------------+----------------|
| 002A           | 42             |
| 0148656C6C6F21 | "Hello!"       |
| 00FFFF         | 65535          |
| 020B1701       | null           |
+----------------+----------------+