二进制输入和输出

Snowflake 支持三种二进制格式或编码方案:hex、base64 和 UTF-8。

本主题内容:

支持的二进制格式概述

hex(默认)

“hex”格式是指十六进制或 base16。在这种格式中,每个字节由两个字符表示(从 0 到 9 的数字和从 AF 的字母)。使用 hex 执行转换时:

从:

到:

备注

二进制

字符串

hex 使用大写字母。

字符串

二进制

hex 不区分大小写。

hex 是默认的二进制格式。

base64

“base64”格式将二进制数据(或字符串数据)编码为可打印的 ASCII 字符(字母、数字和标点符号或数学运算符)。(base64 编码方案的定义见 RFC 4648 (https://tools.ietf.org/html/rfc4648)。)

base64 编码的数据具有以下优点:

  • 由于 base64 编码的数据是 ASCII 纯文本,因此可以将其存储在支持 ASCII 字符数据但不支持 BINARY 数据的系统中。例如,表示音乐(数字样本)的二进制数据或表示普通话字符的 UTF 数据可以编码为 ASCII 文本,并存储在仅支持 ASCII 字符的系统中。

  • 由于 base64 编码的数据不包含控制字符(例如传输结束符、制表符),因此,在传输和接收 base64 编码的数据时,无需担心控制字符会被解释为命令而不是数据。base64 编码的数据与较旧的调制解调器和其他电信设备兼容,这些设备一次发送和接收一个字符的数据,并且没有数据包标头或协议来指示数据包的哪些部分是数据,哪些部分是标头或控制信息。

base64 编码的数据具有以下缺点:

  • 在二进制和可打印的 ASCII 表示形式之间来回转换数据会消耗计算资源。

  • base64 编码的数据需要的存储空间比原始数据多大约 1/3。

下面为感兴趣的读者提供有关编码的技术详细信息:

base64 编码的详细信息

每组三个 8 位字节(总共 24 位)的二进制数据被重新排列成四组,每组 6 位(总共仍为 24 位)。6 位的 64 种可能组合中的每一种都由以下 64 个可打印的 ASCII 字符之一表示:

  • 大写字母 (A – Z)

  • 小写字母 (a – z)

  • 十进制数字 (0 – 9)

  • +

  • /

此外,如果输入的长度不是 3 的整数倍,则会使用字符 = 进行填充。

由于 base64 编码的数据不包含空格字符(例如空格和换行符),因此如果需要,可以将 base64 编码的数据与空格混合使用。例如,如果发射器或接收器限制行的最大长度,则可以通过添加换行符将 base64 编码的数据拆分为单独的行,同时不会损坏数据。使用 base64 执行转换时:

从:

到:

备注

二进制

字符串

base64 不会插入任何空格或换行符。

字符串

二进制

base64 会忽略所有空格和换行符。

UTF-8

UTF-8 格式是指 Unicode 的 UTF-8 字符编码。

UTF-8 用于文本到二进制编码。UTF-8 不能用于二进制到文本编码,因为并非所有可能的 BINARY 值都可以转换为有效的 UTF-8 字符串。

这种格式便于在二进制和字符串之间执行一对一的转换,用于将基础数据重新解释为其中一种类型,而不是进行实际的编码和解码。

二进制值的会话参数

有两个会话参数用于确定如何将二进制值传入和传出 Snowflake:

  • BINARY_INPUT_FORMAT

    指定从 VARCHAR 转换为 BINARY 的函数的 VARCHAR 输入格式。它用于:

    • TO_BINARY 的单实参版本中转换为 BINARY。

    • 将数据加载到 Snowflake 中(如果未指定文件格式选项;有关详细信息,请参阅下文)。

    该参数可以设置为“HEX”、“BASE64”或“UTF-8”(也允许使用“UTF8”)。参数值不区分大小写。默认为“HEX”。

  • BINARY_OUTPUT_FORMAT

    指定从 BINARY 转换为 VARCHAR 的函数的 VARCHAR 输出格式。它用于:

    • TO_CHAR、TO_VARCHAR 的单实参版本中转换为 VARCHAR。

    • 从 Snowflake 卸载数据(如果未指定文件格式选项;有关详细信息,请参阅下文)。

    • 在未显式调用二进制到 varchar 转换的情况下,以人类可读的格式显示二进制数据(例如在 Snowflake Web 界面中)。

    该参数可以设置为“HEX”或“BASE64”。参数值不区分大小写。默认为“HEX”。

    备注

    由于使用 UTF-8 格式从二进制转换为字符串可能会失败,因此,BINARY_OUTPUT_FORMAT 不能设置为 UTF-8。要在这种情况下使用 UTF-8 进行转换,请使用 TO_CHAR、TO_VARCHAR 的双实参版本。

可以在账户、用户和会话级别设置相应参数。执行 SHOW PARAMETERS 命令可查看应用于当前会话中所有操作的当前参数设置。

用于加载/卸载二进制值的文件格式选项

Snowflake 提供了不同于二进制输入和输出会话参数的 BINARY_FORMAT 文件格式选项,可在将数据加载到 Snowflake 表或从其中卸载数据时显式控制二进制格式。

此选项可以设置为“HEX”、“BASE64”或“UTF-8”(值不区分大小写)。此选项会影响数据加载和卸载,而且与其他文件格式选项类似的是,可以通过多种方式指定此选项:

  • 以命名文件格式指定,然后可以在命名暂存区中或直接在 COPY 命令中引用。

  • 在命名暂存区中指定,然后可以直接在 COPY 命令中引用。

  • 直接在 COPY 命令中指定。

数据加载

用于数据加载时,BINARY_FORMAT 指定暂存数据文件中的二进制值格式。此选项将 替换 为会话中的 BINARY_INPUT_FORMAT 参数设置的任何值(请参阅上面的 二进制值的会话参数)。

如果此选项设置为“HEX”或“BASE64”,则如果暂存数据文件中的字符串不是有效的 hex 或 base64,则数据加载可能会失败。在这种情况下,Snowflake 将返回错误,然后执行为 ON_ERROR 复制选项指定的操作。

数据卸载

在数据卸载中使用时,BINARY_FORMAT 选项指定的格式会应用于卸载到指定暂存区中的文件的二进制值。此选项将 替换 为会话中的 BINARY_OUTPUT_FORMAT 参数设置的任何值(请参阅上面的 二进制值的会话参数)。

如果此选项设置为 UTF-8,则如果表中的任何二进制值包含无效的 UTF-8,数据卸载将失败。在这种情况下,Snowflake 会返回错误。

示例输入/输出

BINARY 输入/输出可能会令人困惑,因为“看到的不一定是得到的”。

例如,考虑以下代码序列:

CREATE TABLE binary_table (v VARCHAR, b BINARY);
INSERT INTO binary_table (v, b)
    SELECT 'AB', TO_BINARY('AB');
Copy
SELECT v, b FROM binary_table;
+----+----+
| V  | B  |
|----+----|
| AB | AB |
+----+----+
Copy

v 列 (VARCHAR) 和 b 列的输出似乎相同。然而,b 列的值已转换为二进制。为什么 b 列中的值看起来没有变化?

答案是,TO_BINARY 的实参被视为十六进制数字序列(即使它在引号内,因而看起来像字符串);您看到的 2 个字符实际上被解释为一对十六进制数字,它们表示 1 个字节的二进制数据,而不是 2 个字节的字符串数据。 (如果输入“字符串”包含了十六进制数字以外的字符,这将不可行;结果将是类似于“String '...' is not a legal hex-encoded string”的错误消息。)

此外,当显示 BINARY 数据时,默认情况下它显示为十六进制数字序列。因此,数据以十六进制数字(不是字符串)的形式输入,并显示为十六进制数字,因此它看起来没有变化。

事实上,如果目标是存储一个双字符的字符串“AB”,那么代码是错误的。正确的代码应先使用 HEX_ENCODE 函数将字符串转换为十六进制数字序列(或使用另一个“编码”函数转换为另一种格式,例如 base64),然后再存储数据。下面是这样做的示例。

十六进制(“HEX”)格式示例

输入 BINARY 数据的一种方法是将其编码为十六进制字符的字符串。下面是一个示例。

首先,创建一个包含 BINARY 列的表:

CREATE TABLE demo_binary (b BINARY);
Copy

如果尝试使用 TO_BINARY() 函数插入“普通”字符串,以尝试将其转换为有效的 BINARY 值,则会失败:

INSERT INTO demo_binary (b) SELECT TO_BINARY('HELP', 'HEX');
Copy

下面是错误消息:

100115 (22000): The following string is not a legal hex-encoded value: 'HELP'
Copy

这一次,在插入之前将输入显式转换为十六进制数字的字符串(这将会成功):

INSERT INTO demo_binary (b) SELECT TO_BINARY(HEX_ENCODE('HELP'), 'HEX');
Copy

现在,检索数据:

SELECT TO_VARCHAR(b), HEX_DECODE_STRING(TO_VARCHAR(b)) FROM demo_binary;
+---------------+----------------------------------+
| TO_VARCHAR(B) | HEX_DECODE_STRING(TO_VARCHAR(B)) |
|---------------+----------------------------------|
| 48454C50      | HELP                             |
+---------------+----------------------------------+
Copy

如您所见,默认情况下,输出以十六进制格式显示。要重新获得原始字符串,请使用 HEX_DECODE_STRING 函数(它是之前用于对字符串编码的 HEX_ENCODE_STRING 函数的补充函数)。

以下内容有助于更详细地显示内部发生的情况:

SELECT 'HELP', HEX_ENCODE('HELP'), b, HEX_DECODE_STRING(HEX_ENCODE('HELP')),
   TO_VARCHAR(b), HEX_DECODE_STRING(TO_VARCHAR(b)) FROM demo_binary;
Copy

输出:

SELECT 'HELP', HEX_ENCODE('HELP'), b, HEX_DECODE_STRING(HEX_ENCODE('HELP')),
   TO_VARCHAR(b), HEX_DECODE_STRING(TO_VARCHAR(b)) FROM demo_binary;
+--------+--------------------+----------+---------------------------------------+---------------+----------------------------------+
| 'HELP' | HEX_ENCODE('HELP') | B        | HEX_DECODE_STRING(HEX_ENCODE('HELP')) | TO_VARCHAR(B) | HEX_DECODE_STRING(TO_VARCHAR(B)) |
|--------+--------------------+----------+---------------------------------------+---------------+----------------------------------|
| HELP   | 48454C50           | 48454C50 | HELP                                  | 48454C50      | HELP                             |
+--------+--------------------+----------+---------------------------------------+---------------+----------------------------------+
Copy

BASE64 格式示例

在阅读本部分之前,可能需要阅读上面的“十六进制格式”部分。基本概念很相似,但“十六进制格式”部分更详细地进行了解释。

首先,创建一个包含 BINARY 列的表:

CREATE TABLE demo_binary (b BINARY);
Copy

插入一行:

INSERT INTO demo_binary (b) SELECT TO_BINARY(BASE64_ENCODE('HELP'), 'BASE64');
Copy

检索该行:

SELECT 'HELP', BASE64_ENCODE('HELP'),
   BASE64_DECODE_STRING(BASE64_ENCODE('HELP')),
   TO_VARCHAR(b, 'BASE64'), 
   BASE64_DECODE_STRING(TO_VARCHAR(b, 'BASE64'))
   FROM demo_binary;
+--------+-----------------------+---------------------------------------------+-------------------------+-----------------------------------------------+
| 'HELP' | BASE64_ENCODE('HELP') | BASE64_DECODE_STRING(BASE64_ENCODE('HELP')) | TO_VARCHAR(B, 'BASE64') | BASE64_DECODE_STRING(TO_VARCHAR(B, 'BASE64')) |
|--------+-----------------------+---------------------------------------------+-------------------------+-----------------------------------------------|
| HELP   | SEVMUA==              | HELP                                        | SEVMUA==                | HELP                                          |
+--------+-----------------------+---------------------------------------------+-------------------------+-----------------------------------------------+
Copy

UTF-8 格式示例

首先,创建一个包含 BINARY 列的表:

CREATE TABLE demo_binary (b BINARY);
Copy

插入一行:

INSERT INTO demo_binary (b) SELECT TO_BINARY('HELP', 'UTF-8');
Copy

检索该行:

SELECT 'HELP', TO_VARCHAR(b, 'UTF-8')
   FROM demo_binary;
+--------+------------------------+
| 'HELP' | TO_VARCHAR(B, 'UTF-8') |
|--------+------------------------|
| HELP   | HELP                   |
+--------+------------------------+
Copy
语言: 中文