数值数据类型¶
本主题介绍 Snowflake 中支持的数值数据类型,以及支持的数值常量和字面量格式。
定点数的数据类型¶
Snowflake 支持以下定点数数据类型。
NUMBER¶
数字最多可达 38 位,精度和小数位数可选:
- 精度:
允许的总位数。
- 小数位数:
小数点右侧允许的位数。
默认情况下,精度为 38,小数位数为 0;即 NUMBER(38, 0)。精度限制了可插入或强制转换为给定类型列的值的范围。例如,值 999 适合放入 NUMBER(38,0),但不适合放入 NUMBER(2,0)。
因为精度是允许的总位数,所以如果小数点左边的位数超过该列的精度减去其小数位数,则无法将值加载到 NUMBER 列中。例如,NUMBER(20, 2) 允许小数点左侧有 18 位数字,小数点右侧有两位数字,总共为 20 位。
*最大小数位数*(即小数点右侧的位数)为 37。如果数字的有效位数少于 38 位,但其最低有效位数位于小数点后第 37 位之后(例如 0.0000000000000000000000000000000000000012 [1.2e-39]),则在不损失一些精度数位的情况下无法表示。
备注
如果将数据转换为精度较低的其他数据类型,然后再转换回精度较高的数据类型,则数据可能会出现精度损失。例如,如果将 NUMBER(38,37) 值转换为 DOUBLE 值(其精度约为 15 位小数数字),然后再转换回 NUMBER,则会损失精度。
Snowflake 还支持 FLOAT 数据类型,该类型允许的值范围更广,但精度较低。
DECIMAL、DEC、NUMERIC¶
与 NUMBER 同义。
INT、INTEGER、BIGINT、SMALLINT、TINYINT、BYTEINT¶
与 NUMBER 同义,但不能指定精度和小数位数(即始终默认为 NUMBER(38, 0))。因此,对于所有 INTEGER 数据类型,值范围都是从 -99999999999999999999999999999999999999 到 +99999999999999999999999999999999999999(含)的所有整数值。
各种不同的名称(例如 TINYINT、BYTEINT 等)是为了简化从其他系统移植的过程,以及建议指定类型的列的预期值范围。
精度和小数位数对存储大小的影响¶
精度(总位数)不影响存储。对于精度不同的列(例如 NUMBER(2,0) 和 NUMBER(38,0))中相同的数字,其存储要求是相同的。对于每个微分区,Snowflake 会确定给定列的最小值和最大值,并会使用该信息确定分区中该列的所有值的存储大小。例如:
如果列仅包含
-128和+127之间的值,则每个值将占用 1 个字节(未压缩)。如果列中的最大值为
10000000,则其中每个值将占用 4 个字节(未压缩)。
但是,小数位(小数点后面的位数)会影响存储。例如,相同的值存储在类型为 NUMBER(10,5) 的列中比存储在类型为 NUMBER(5,0) 的列中要占用更多的空间。此外,处理小数位数较大的值时速度可能会略慢,并且会消耗更多内存。
为了节省空间,Snowflake 会在将值写入存储之前对其进行压缩。压缩量取决于数据值和其他因素。
表中的定点数据类型示例¶
下面的语句创建了一个表,包含各种定点数据类型的列:
CREATE OR REPLACE TABLE test_fixed(
num0 NUMBER,
num10 NUMBER(10,1),
dec20 DECIMAL(20,2),
numeric30 NUMERIC(30,3),
int1 INT,
int2 INTEGER);
DESC TABLE test_fixed;
+-----------+--------------+--------+-------+---------+-------------+------------+-------+------------+---------+-------------+----------------+
| name | type | kind | null? | default | primary key | unique key | check | expression | comment | policy name | privacy domain |
|-----------+--------------+--------+-------+---------+-------------+------------+-------+------------+---------+-------------+----------------|
| NUM0 | NUMBER(38,0) | COLUMN | Y | NULL | N | N | NULL | NULL | NULL | NULL | NULL |
| NUM10 | NUMBER(10,1) | COLUMN | Y | NULL | N | N | NULL | NULL | NULL | NULL | NULL |
| DEC20 | NUMBER(20,2) | COLUMN | Y | NULL | N | N | NULL | NULL | NULL | NULL | NULL |
| NUMERIC30 | NUMBER(30,3) | COLUMN | Y | NULL | N | N | NULL | NULL | NULL | NULL | NULL |
| INT1 | NUMBER(38,0) | COLUMN | Y | NULL | N | N | NULL | NULL | NULL | NULL | NULL |
| INT2 | NUMBER(38,0) | COLUMN | Y | NULL | N | N | NULL | NULL | NULL | NULL | NULL |
+-----------+--------------+--------+-------+---------+-------------+------------+-------+------------+---------+-------------+----------------+
浮点数的数据类型¶
Snowflake 支持以下浮点数数据类型。
FLOAT、FLOAT4、FLOAT8¶
名称 FLOAT、FLOAT4 和 FLOAT8 是为了与其他系统兼容;Snowflake 将这三类数值都视为 64 位浮点数。
精度¶
Snowflake 使用双精度(64 位)IEEE 754 浮点数。
精度约为 15 位。例如,对于整数,取值范围为 -9007199254740991 到 +9007199254740991(-253 + 1 到 +253 - 1)。浮点值的范围约为 10-308 到 10+308。Snowflake 可以表示介于约 10-324 到 10-308 之间的更极端的值,采用较低的精度。有关更多详细信息,请参阅 关于双精度数的维基百科文章 (link removed)。
Snowflake 支持定点数据类型 NUMBER,尽管指数范围较小,但允许更高的精度。
特殊值¶
Snowflake 支持以下 FLOAT 类型的特殊值:
符号 'NaN'、'inf' 和 '-inf' 必须放在单引号内,并且不区分大小写。
'NaN' 的比较语义与 IEEE 754 标准在以下方面有所不同:
条件 |
Snowflake |
IEEE 754 |
注释 |
|---|---|---|---|
|
|
|
在 Snowflake 中, |
|
|
|
在 Snowflake 中, |
舍入误差¶
浮点运算在最低有效位数中可能会有微小的舍入误差。舍入误差可能发生在任何类型的浮点处理中,包括三角函数、统计函数和地理空间函数。
以下列表显示了舍入误差的注意事项:
每次执行查询时,误差都可能有所不同。
当操作数具有不同的精度或小数位数时,误差可能会更大。
误差可能会累积,尤其是当聚合函数(例如 SUM 或 AVG)处理大量行时。在聚合之前类型转换为定点数据类型可以减少或消除这些误差。
舍入误差不仅会在使用 SQL 时发生,在处理 Snowflake 中运行(例如在 UDFs 和 存储过程 中)的其他代码(例如 Java、JavaScript 或 Python)时也会发生。
在比较两个浮点数时,Snowflake 建议比较近似相等性而不是完全相等性。
通过使用精确的 DECFLOAT 数据类型,可能会避免这类近似误差。
DOUBLE、DOUBLE PRECISION、REAL¶
与 FLOAT 同义。
表中的浮点数据类型示例¶
下面的语句创建了一个表,包含各种浮点数据类型的列:
CREATE OR REPLACE TABLE test_float(
double1 DOUBLE,
float1 FLOAT,
dp1 DOUBLE PRECISION,
real1 REAL);
DESC TABLE test_float;
+---------+-------+--------+-------+---------+-------------+------------+-------+------------+---------+-------------+----------------+
| name | type | kind | null? | default | primary key | unique key | check | expression | comment | policy name | privacy domain |
|---------+-------+--------+-------+---------+-------------+------------+-------+------------+---------+-------------+----------------|
| DOUBLE1 | FLOAT | COLUMN | Y | NULL | N | N | NULL | NULL | NULL | NULL | NULL |
| FLOAT1 | FLOAT | COLUMN | Y | NULL | N | N | NULL | NULL | NULL | NULL | NULL |
| DP1 | FLOAT | COLUMN | Y | NULL | N | N | NULL | NULL | NULL | NULL | NULL |
| REAL1 | FLOAT | COLUMN | Y | NULL | N | N | NULL | NULL | NULL | NULL | NULL |
+---------+-------+--------+-------+---------+-------------+------------+-------+------------+---------+-------------+----------------+
备注
DESC TABLE 命令的 type 列显示的数据类型 FLOAT 不仅针对 FLOAT,还针对 FLOAT 的同义词(例如 DOUBLE、DOUBLE PRECISION 和 REAL)。
DECFLOAT¶
十进制浮点数 (DECFLOAT) 数据类型精确存储数字,精度高达 38 位有效数字,并使用以 10 为底的动态指数来表示非常大或非常小的值。指数范围为 -16383 到 16384,允许值大约介于 -10^(16384) 到 10^(16384) 之间。DECFLOAT 数据类型支持变量小数位数,因此小数位数会根据存储的特定值而变化。与 FLOAT 数据类型以近似值表示数值不同,DECFLOAT 数据类型会在指定的精度范围内表示精确值。
DECFLOAT 数据类型不支持以下 FLOAT 数据类型支持的 特殊值:'NaN'`(非数字),:code:'inf'(无穷大),以及 :code:'-inf'`(负无穷大)。
DECFLOAT 数据类型用例¶
当您需要精确的小数结果和同一列中的宽、变量小数位数时,使用 DECFLOAT 数据类型。
DECFLOAT 数据类型适用于以下一般用例:
您正在引入数据,传入数值的范围未知或高度可变。
您需要精确的数值;例如,分类账、税收或合规性。
您正在从依赖 IEEE 754 十进制表示或 128 位十进制数的系统进行迁移。这些迁移可能会受到其他 Snowflake 数据类型的精度或范围限制的阻碍。
您想避免
Number out of representable range对高精度数值进行求和、乘法或除法运算时出现的错误。
例如,您可以使用以下特定用例的 DECFLOAT 数据类型:
您正在从 Oracle DECIMAL 或 DB2 DECFLOAT 列引入异构扩展的数据。
您正在执行的财务建模涉及到难以预测的结果规模的计算。
您正在运行从纳单位到天文单位的科学测量。
您可以继续使用固定小数位数列的 NUMBER 数据类型或用于高吞吐量分析的 FLOAT 数据类型,其中不精确的结果是可以接受的。
使用 DECFLOAT 数据类型说明¶
如果运算产生的结果超过 38 位,则 DECFLOAT 值四舍五入到 38 位精度,最低有效数字根据当前舍入模式四舍五入。对于 DECFLOAT 值,Snowflake 使用 半向上舍入模式 (link removed)。
当您指定 DECFLOAT 值或转换为 DECFLOAT 值时,避免在 SQL 中使用数值字面量。如果在 SQL 中使用数值字面量,值解释为 NUMBER 或 FLOAT 值,然后再转换为 DECFLOAT 值,这可能会导致范围错误或准确性损失。相反,使用任一字符串字面量,例如
SELECT '<value>'::DECFLOAT,或 DECFLOAT 字面量,例如SELECTDECFLOAT '<value>'。当混合操作 DECFLOAT 值和其他数值类型的值时,强制转换更喜欢 DECFLOAT 值。例如,当您添加以下 NUMBER 类型和 DECFLOAT 类型值时,结果是 DECFLOAT 值。
使用 DECFLOAT 类型可能会导致存储消耗增加。
支持 DECFLOAT 数据类型的驱动程序和驱动程序版本¶
以下 Snowflake 驱动程序和驱动程序版本支持 DECFLOAT 数据类型。可能需要将驱动程序更新到支持 DECFLOAT 的版本。
驱动程序 |
支持的最低版本 |
备注 |
|---|---|---|
Snowflake Connector for Python |
3.14.1 |
Pandas DataFrames 不支持 DECFLOAT 类型。 |
ODBC |
3.12.0 |
无。 |
JDBC |
3.27.0 |
无。 |
Go Snowflake 驱动程序 |
1.17.0 |
无。 |
SQL API |
2.0.0 |
无。 |
不受支持的驱动程序会将 DECFLOAT 值处理为 TEXT 值。对于某些驱动程序,必须设置驱动程序参数以将 DECFLOAT 类型映射为语言的原生类型。有关更多信息,请参阅 驱动程序。
DECFLOAT 数据类型的限制¶
以下限制适用于 DECFLOAT 数据:
DECFLOAT 值不能存储为 半结构化数据类型 或 结构化数据类型。
要将 DECFLOAT 值作为这些类型之一的字符串进行存储,您可以将 DECFLOAT 值 转换 为 VARCHAR 值。
以下类型的表不支持 DECFLOAT 值:
外部格式的表,例如 Iceberg
混合表
在使用非 SQL 语言(例如 Python 或 Java)编写的存储过程或用户定义函数 (UDFs) 中,不支持 DECFLOAT 数据类型。
Snowpark 不支持 DECFLOAT 数据类型。
Snowsight 对 DECFLOAT 数据类型的支持有限。
以下功能不支持 DECFLOAT 数据类型:
NUMBER 和 FLOAT 类型可能提供比 DECFLOAT 类型更好的性能。
DECFLOAT 数据类型示例¶
以下示例使用 DECFLOAT 数据类型:
显示 DECFLOAT 和 FLOAT 之间的差异¶
以下示例显示了 DECFLOAT 和 FLOAT 数据类型之间的差异:
创建一个表,其中包含 DECFLOAT 列和 FLOAT 列,然后将两种类型的相同值插入到表中:
CREATE OR REPLACE TABLE decfloat_sample ( id INT, decfloat_val DECFLOAT, float_val FLOAT); INSERT INTO decfloat_sample VALUES ( 1, DECFLOAT '123e7000', FLOAT '123e7000' ), ( 2, 12345678901234567890123456789::DECFLOAT, 12345678901234567890123456789::FLOAT ), ( 3, '-4.2e-5432'::DECFLOAT, '-4.2e-5432'::FLOAT ), ( 4, '1.00000000000000000000000000000000000014'::DECFLOAT, '1.00000000000000000000000000000000000014'::FLOAT ), ( 5, '1.00000000000000000000000000000000000015'::DECFLOAT, '1.00000000000000000000000000000000000015'::FLOAT );
该语句通过以下方式插入 DECFLOAT 值:
第一个值是通过使用 DECFLOAT 字面量插入。
第二个值通过将 INTEGER 值转换为 DECFLOAT 值插入。
第三个、第四个和第五个值通过将 VARCHAR 值转换为 DECFLOAT 值插入。
要显示类型,请使用 DESC TABLE 命令来描述该表。
任一列的表定义中均未指定精度,但输出显示 DECFLOAT 数据类型最多支持 38 位有效数字的精度:
DESC TABLE decfloat_sample;
+--------------+--------------+--------+-------+---------+-------------+------------+-------+------------+---------+-------------+----------------+ | name | type | kind | null? | default | primary key | unique key | check | expression | comment | policy name | privacy domain | |--------------+--------------+--------+-------+---------+-------------+------------+-------+------------+---------+-------------+----------------| | ID | NUMBER(38,0) | COLUMN | Y | NULL | N | N | NULL | NULL | NULL | NULL | NULL | | DECFLOAT_VAL | DECFLOAT(38) | COLUMN | Y | NULL | N | N | NULL | NULL | NULL | NULL | NULL | | FLOAT_VAL | FLOAT | COLUMN | Y | NULL | N | N | NULL | NULL | NULL | NULL | NULL | +--------------+--------------+--------+-------+---------+-------------+------------+-------+------------+---------+-------------+----------------+
要显示值的差异,请使用 SELECT 语句查询该表:
SELECT * FROM decfloat_sample;
+----+-----------------------------------------+------------------------+ | ID | DECFLOAT_VAL | FLOAT_VAL | |----+-----------------------------------------+------------------------| | 1 | 1.23e7002 | inf | | 2 | 12345678901234567890123456789 | 1.23456789012346e+28 | | 3 | -4.2e-5432 | -0 | | 4 | 1.0000000000000000000000000000000000001 | 1 | | 5 | 1.0000000000000000000000000000000000002 | 1 | +----+-----------------------------------------+------------------------+
输出显示以下差异:
第一行显示 DECFLOAT 类型支持的值范围比 FLOAT 类型更大。DECFLOAT 值非常大 (
1.23e7002)。FLOAT 值为inf,这意味着该值大于 FLOAT 类型所能表示的任何数值。第二行显示 DECFLOAT 类型完全保留指定的值。FLOAT 值是以科学记数法存储的近似值。
第三行显示 DECFLOAT 类型支持非常小的值 (
-4.2e-5432)。FLOAT 值近似为-0。第四行和第五行显示 DECFLOAT 类型支持高达 38 位的精度,并对超出限制的值使用舍入规则。FLOAT 值在两行中近似为
1。
在聚合函数中使用 DECFLOAT 值¶
以下示例演示了在聚合函数中使用 DECFLOAT 值:
创建表,然后将 DECFLOAT 值插入表中:
CREATE OR REPLACE TABLE decfloat_agg_sample (decfloat_val DECFLOAT); INSERT INTO decfloat_agg_sample VALUES (DECFLOAT '1e1000'), (DECFLOAT '-2.47e999'), (DECFLOAT '22e-75');
使用一些聚合函数查询表:
SELECT SUM(decfloat_val), AVG(decfloat_val), MAX(decfloat_val), MIN(decfloat_val) FROM decfloat_agg_sample;
+-------------------+-------------------+-------------------+-------------------+ | SUM(DECFLOAT_VAL) | AVG(DECFLOAT_VAL) | MAX(DECFLOAT_VAL) | MIN(DECFLOAT_VAL) | |-------------------+-------------------+-------------------+-------------------| | 7.53e999 | 2.51e999 | 1e1000 | -2.47e999 | +-------------------+-------------------+-------------------+-------------------+
数值常量¶
术语 常量*(也称为 *字面量)是指固定的数据值。数值常量支持以下格式:
[+-][digits][.digits][e[+-]digits]
其中:
+或-表示正值或负值。默认为正值。digits是 0 到 9 范围内的一个或多个数字。e(或E)表示科学记数法中的指数。指数标记后必须至少有一位数字(如果存在)。
以下数字都是受支持的数值常量的示例:
15
+1.34
0.2
15e-03
1.234E2
1.234E+2
-1