二进制输入和输出¶
Snowflake 支持三种二进制格式或编码方案:hex、base64 和 UTF-8。
本主题内容:
支持的二进制格式概述¶
hex(默认)¶
“hex”格式是指十六进制或 base16。在这种格式中,每个字节由两个字符表示(从 0 到 9 的数字和从 A
到 F
的字母)。使用 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');SELECT v, b FROM binary_table; +----+----+ | V | B | |----+----| | AB | AB | +----+----+
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);如果尝试使用 TO_BINARY() 函数插入“普通”字符串,以尝试将其转换为有效的 BINARY 值,则会失败:
INSERT INTO demo_binary (b) SELECT TO_BINARY('HELP', 'HEX');下面是错误消息:
100115 (22000): The following string is not a legal hex-encoded value: 'HELP'这一次,在插入之前将输入显式转换为十六进制数字的字符串(这将会成功):
INSERT INTO demo_binary (b) SELECT TO_BINARY(HEX_ENCODE('HELP'), 'HEX');现在,检索数据:
SELECT TO_VARCHAR(b), HEX_DECODE_STRING(TO_VARCHAR(b)) FROM demo_binary; +---------------+----------------------------------+ | TO_VARCHAR(B) | HEX_DECODE_STRING(TO_VARCHAR(B)) | |---------------+----------------------------------| | 48454C50 | HELP | +---------------+----------------------------------+
如您所见,默认情况下,输出以十六进制格式显示。要重新获得原始字符串,请使用 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;
输出:
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 | +--------+--------------------+----------+---------------------------------------+---------------+----------------------------------+
BASE64 格式示例¶
在阅读本部分之前,可能需要阅读上面的“十六进制格式”部分。基本概念很相似,但“十六进制格式”部分更详细地进行了解释。
首先,创建一个包含 BINARY 列的表:
CREATE TABLE demo_binary (b BINARY);插入一行:
INSERT INTO demo_binary (b) SELECT TO_BINARY(BASE64_ENCODE('HELP'), 'BASE64');检索该行:
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 | +--------+-----------------------+---------------------------------------------+-------------------------+-----------------------------------------------+
UTF-8 格式示例¶
首先,创建一个包含 BINARY 列的表:
CREATE TABLE demo_binary (b BINARY);插入一行:
INSERT INTO demo_binary (b) SELECT TO_BINARY('HELP', 'UTF-8');检索该行:
SELECT 'HELP', TO_VARCHAR(b, 'UTF-8') FROM demo_binary; +--------+------------------------+ | 'HELP' | TO_VARCHAR(B, 'UTF-8') | |--------+------------------------| | HELP | HELP | +--------+------------------------+