数据类型转换¶
在许多情况下,一种数据类型的值可以转换为另一种数据类型。例如,可以将 INTEGER 转换为 浮点数据类型。转换数据类型称为 类型转换。
本主题内容:
显式类型转换与隐式类型转换¶
用户可以将值从一种数据类型显式转换为另一种数据类型。这称为 显式类型转换。
在某些情况下,Snowflake 会自动将值转换为另一种数据类型。这称为 隐式类型转换 或 强制转换。
显式类型转换¶
用户可以使用以下任一选项显式转换值:
例如:
SELECT CAST('2022-04-01' AS DATE); SELECT '2022-04-01'::DATE; SELECT TO_DATE('2022-04-01');
在允许使用一般表达式(包括 WHERE 子句)的大多数上下文中,允许执行类型转换。例如:
SELECT date_column FROM log_table WHERE date_column >= '2022-04-01'::DATE;
隐式类型转换(“强制转换”)¶
当函数(或运算符)需要的数据类型与实参(或操作数)不同但兼容时,就会发生强制转换。
函数或存储过程的示例:
下面的代码将列
my_integer_column
中的 INTEGER 值强制转换为 FLOAT,以便传递给需要 FLOAT 的函数my_float_function()
:SELECT my_float_function(my_integer_column) FROM my_table;
运算符示例:
下面的代码将 INTEGER 值
17
强制转换为 VARCHAR,以便使用||
运算符连接这些值:SELECT 17 || '76';
此 SELECT 语句的结果是字符串
'1776'
。以下语句将列
my_integer_column
中的值 INTEGER 强制转换为 FLOAT,以便使用<
比较运算符将该值与值my_float_column
进行比较:SELECT ... FROM my_table WHERE my_integer_column < my_float_column;
并非所有上下文(例如,并非所有运算符)都支持强制转换。
类型转换和优先级¶
在表达式内进行类型转换时,代码必须考虑转换运算符相对于表达式中其他运算符的优先级。
请参考以下示例:
SELECT height * width::VARCHAR || " square meters" FROM dimensions;
转换运算符的优先级高于算术运算符 *
(乘法),因此该语句可解释为:
... height * (width::VARCHAR) ...
要转换表达式 height * width
的结果,请使用括号,如下所示:
SELECT (height * width)::VARCHAR || " square meters" FROM dimensions;
又例如,请注意以下语句:
SELECT -0.0::FLOAT::BOOLEAN;
您可能希望将其解释为:
SELECT (-0.0::FLOAT)::BOOLEAN;
因此返回 FALSE (0 = FALSE,1 = TRUE)。
但是,转换运算符的优先级高于一元减号(负号)运算符,因此该语句被解释为:
SELECT -(0.0::FLOAT::BOOLEAN);
因此会导致产生错误消息,因为一元减号不能应用于 BOOLEAN。
可转换的数据类型¶
下表显示了 Snowflake 中的有效数据类型转换。该表还显示了 Snowflake 可以自动执行的强制转换。
备注
在内部,CAST 函数和 ::
运算符会调用相应的转换函数。例如,如果将 NUMBER 转换为 BOOLEAN,则 Snowflake 将调用 TO_BOOLEAN 函数。当通过转换间接调用函数,以及直接调用函数时,各个转换函数的使用说明均适用。例如,如果执行 CAST(my_decimal_column as BOOLEAN)
,则应用使用 DECIMAL 值调用 TO_BOOLEAN
的规则。为方便起见,下表中的“备注”列包括了指向相关转换函数的链接。
有关 半结构化类型 和 结构化类型 之间的转换的详细信息,请参阅 转换结构化类型和半结构化类型。
源数据类型 |
目标数据类型 |
可转换 |
可强制转换 |
转换函数 |
备注 |
---|---|---|---|---|---|
ARRAY |
|||||
✔ |
❌ |
||||
✔ |
✔ |
||||
✔ |
✔ |
||||
BINARY |
|||||
✔ |
❌ |
||||
✔ |
❌ |
||||
BOOLEAN |
|||||
✔ |
❌ |
||||
✔ |
✔ |
例如,从 TRUE 到“true”。 |
|||
✔ |
✔ |
||||
DATE |
|||||
✔ |
✔ |
||||
✔ |
✔ |
||||
✔ |
❌ |
||||
FLOAT . (浮点数) |
|||||
✔ |
✔ |
例如,从 0.0 到 FALSE。 |
|||
✔ |
✔ |
||||
✔ |
✔ |
||||
✔ |
✔ |
||||
GEOGRAPHY |
|||||
✔ |
❌ |
||||
GEOMETRY |
|||||
✔ |
❌ |
||||
NUMBER[(p,s)] . (固定点数,包括 INTEGER) |
|||||
✔ |
✔ |
例如,从 0 到 FALSE。 |
|||
✔ |
✔ |
||||
✔ |
✔ |
||||
✔ |
✔ |
||||
✔ |
✔ |
||||
OBJECT |
|||||
✔ |
❌ |
||||
✔ |
❌ |
||||
✔ |
✔ |
||||
TIME |
|||||
✔ |
✔ |
||||
✔ |
❌ |
||||
TIMESTAMP |
|||||
✔ |
✔ |
||||
✔ |
✔ |
||||
✔ |
✔ |
||||
✔ |
❌ |
||||
VARCHAR |
|||||
✔ |
✔ |
例如,从“false”到 FALSE。 |
|||
✔ |
✔ |
||||
✔ |
✔ |
例如,从“12.34”到 12.34。 |
|||
✔ |
✔ |
例如,从“12.34”到 12.34。 |
|||
✔ |
✔ |
||||
✔ |
✔ |
||||
✔ |
❌ |
||||
VARIANT |
|||||
✔ |
✔ |
||||
✔ |
✔ |
例如,从包含“false”的 VARIANT 到 FALSE。 |
|||
✔ |
✔ |
||||
✔ |
✔ |
||||
✔ |
❌ |
||||
✔ |
✔ |
||||
✔ |
✔ |
||||
✔ |
✔ |
||||
✔ |
✔ |
||||
✔ |
✔ |
||||
✔ |
❌ |
VARIANT 必须包含 FLOAT 或 INT 类型的 ARRAY。 |
|||
VECTOR |
|||||
✔ |
✔ |
备注:
对于列出的每个数据类型(例如 FLOAT),规则适用于该数据类型的所有别名(例如 FLOAT 的规则适用于 DOUBLE,也就是 FLOAT 的别名)。
使用说明¶
除非另有说明,否则以下规则适用于显式类型转换和隐式类型转换。
转换不仅取决于数据类型,还取决于源的值。例如:
VARCHAR “123”可以转换为数值,但 VARCHAR“xyz”不能转换为数值。
能否转换类型为 VARIANT 指定值取决于 VARIANT 内部 的数据类型。例如,如果 VARIANT 包含类型为 TIME 的值,则不能将 VARIANT 转换为 TIMESTAMP,因为不能将 TIME 转换为 TIMESTAMP。
如果可能,请传入相同类型的实参。避免传入不同类型的实参。
如果其中一个实参是数字,则函数会 强制转换 非数值字符串实参(例如
'a string'
)和不是类型 NUMBER(18,5) 常量的字符串实参。对于不是常量的数值字符串实参,如果 NUMBER(18,5) 不足以表示数值,则应将实参 转换 为可以表示该值的类型。
对于某些数据类型对,转换可能会导致精度下降。例如:
将 FLOAT 转换为 INTEGER 会舍入值。
如果不能用浮点数精确表示定点数,则将值从定点数(例如 NUMBER(38, 0))转换为浮点数(例如,FLOAT)可能会导致舍入误差或截断。
将 TIMESTAMP 转换为 DATE 将移除有关一天中时间的信息。
尽管 Snowflake 会在某些可能发生精度损失的情况下转换值,但 Snowflake 不允许在可能发生精度损失的其他情况下执行转换。例如,当转换会出现以下情况时,Snowflake 不允许执行转换:
截断 VARCHAR 值。例如,Snowflake 不会将 VARCHAR(10) 隐式或显式转换为 VARCHAR(5)。
导致除最低有效位数以外的数字丢失。例如,以下语句会失败:
select 12.3::FLOAT::NUMBER(3,2);
在此示例中,数字
12.3
在小数点之前有两位数字,但数据类型NUMBER(3,2)
在小数点之前只有一位数字的空间。从精度较低的类型转换为精度较高的类型时,转换会使用默认值。例如,将 DATE 转换为 TIMESTAMP_NTZ 会导致小时、分钟、秒和小数秒值设置为 0。
当 FLOAT 值被转换为 VARCHAR 时,尾零将省略。
例如,以下语句会创建一个表并插入包含 VARCHAR、FLOAT 和 VARIANT 的行。VARIANT 使用包含用尾零表示浮点值的 JSON 构建。
create or replace table tmp ( varchar1 varchar, float1 float, variant1 variant ); insert into tmp select '5.000', 5.000, parse_json('{"Loan Number": 5.000}');
以下 SELECT 语句将 VARIANT 列中的 FLOAT 列和 FLOAT 值显式转换为 VARCHAR。在每种情况下,VARCHAR 均不包含尾零:
select varchar1, float1::varchar, variant1:"Loan Number"::varchar from tmp; +----------+-----------------+---------------------------------+ | VARCHAR1 | FLOAT1::VARCHAR | VARIANT1:"LOAN NUMBER"::VARCHAR | |----------+-----------------+---------------------------------| | 5.000 | 5 | 5 | +----------+-----------------+---------------------------------+
某些操作可以返回不同的数据类型,具体取决于条件表达式。例如,以下 COALESCE 调用返回的数据类型略有不同,具体取决于输入值:
select system$typeof(ifnull(12.3, 0)), system$typeof(ifnull(NULL, 0)); +--------------------------------+--------------------------------+ | SYSTEM$TYPEOF(IFNULL(12.3, 0)) | SYSTEM$TYPEOF(IFNULL(NULL, 0)) | +--------------------------------+--------------------------------+ | NUMBER(3,1)[SB1] | NUMBER(1,0)[SB1] | +--------------------------------+--------------------------------+
如果表达式具有多个可能的数据类型,则 Snowflake 会根据实际结果选择数据类型。(有关计算中的精度和标度的更多信息,请参阅 算术运算的小数位数和精度。)如果查询生成多个结果(例如,多行结果),则 Snowflake 会选择能够保存每个单独结果的数据类型。
某些应用程序(如 SnowSQL)和某些图形用户界面(例如 Classic Console)在显示数据时会应用自己的转换和格式设置规则。例如,SnowSQL 会将 BINARY 值显示为仅包含十六进制数字的字符串;该字符串是通过隐式调用转换函数生成的。因此,SnowSQL 显示的数据可能无法明确指示 Snowflake 强制转换了哪些数据。