整数类型
类型 TINYINT
, SMALLINT
, INTEGER
, BIGINT
和 HUGEINT
存储整数,即没有小数部分的数字,范围各不相同。尝试存储超出允许范围的值将导致错误。
类型 UTINYINT
, USMALLINT
, UINTEGER
, UBIGINT
和 UHUGEINT
存储无符号整数。尝试存储负数或超出允许范围的值将导致错误。
名称 | 别名 | 最小值 | 最大值 |
---|---|---|---|
TINYINT |
INT1 |
-128 | 127 |
SMALLINT |
INT2 , INT16 SHORT |
-32768 | 32767 |
INTEGER |
INT4 , INT32 , INT , SIGNED |
-2147483648 | 2147483647 |
BIGINT |
INT8 , INT64 LONG |
-9223372036854775808 | 9223372036854775807 |
HUGEINT |
INT128 |
-170141183460469231731687303715884105728 | 170141183460469231731687303715884105727 |
UTINYINT |
- | 0 | 255 |
USMALLINT |
- | 0 | 65535 |
UINTEGER |
- | 0 | 4294967295 |
UBIGINT |
- | 0 | 18446744073709551615 |
UHUGEINT |
- | 0 | 340282366920938463463374607431768211455 |
整数类型是常见的选择,因为它在范围、存储大小和性能之间提供了最佳平衡。SMALLINT
类型通常仅在磁盘空间非常宝贵时使用。BIGINT
和HUGEINT
类型设计用于当整数类型的范围不足时使用。
定点小数
数据类型 DECIMAL(WIDTH, SCALE)
(也可使用别名 NUMERIC(WIDTH, SCALE)
)表示一个精确的定点十进制值。在创建 DECIMAL
类型的值时,可以指定 WIDTH
和 SCALE
来定义字段中可以容纳的十进制值的大小。WIDTH
字段决定了可以容纳多少位数字,而 scale
决定了小数点后的位数。例如,类型 DECIMAL(3, 2)
可以容纳值 1.23
,但不能容纳值 12.3
或值 1.234
。如果未指定,默认的 WIDTH
和 SCALE
是 DECIMAL(18, 3)
。
两个定点小数的加法、减法和乘法会返回另一个具有所需WIDTH
和SCALE
的定点小数,以包含精确结果,如果所需的WIDTH
超过当前支持的最大WIDTH
(目前为38),则会抛出错误。
定点小数的除法通常不会产生有限小数扩展的数字。因此,DuckDB对所有涉及定点小数的除法使用近似的浮点算术,并相应地返回浮点数据类型。
在内部,小数根据其指定的WIDTH
表示为整数。
宽度 | 内部 | 大小(字节) |
---|---|---|
1-4 | INT16 |
2 |
5-9 | INT32 |
4 |
10-18 | INT64 |
8 |
19-38 | INT128 |
16 |
性能可能会因为不必要地使用过大的小数而受到影响。特别是宽度超过19的小数值会很慢,因为涉及INT128
类型的算术运算比涉及INT32
或INT64
类型的运算要昂贵得多。因此,建议坚持使用WIDTH
为18
或以下的值,除非有充分的理由说明这不够。
浮点类型
数据类型 FLOAT
和 DOUBLE
精度是可变精度的数字类型。实际上,这些类型通常是IEEE标准754的二进制浮点运算(分别为单精度和双精度)的实现,只要底层处理器、操作系统和编译器支持。
Name | Aliases | Description |
---|---|---|
FLOAT |
FLOAT4 , REAL |
单精度浮点数(4字节) |
DOUBLE |
FLOAT8 |
双精度浮点数(8字节) |
与定点数据类型类似,从字面量或其他数据类型转换为浮点类型时,无法精确表示的输入会存储为近似值。然而,预测哪些输入会受到影响可能更加困难。例如,1.3::DECIMAL(1, 0) - 0.7::DECIMAL(1, 0) != 0.6::DECIMAL(1, 0)
并不令人惊讶,但 1.3::FLOAT - 0.7::FLOAT != 0.6::FLOAT
可能会让人感到意外。
此外,定点十进制数据类型的乘法、加法和减法是精确的,而这些操作在浮点二进制数据类型上只是近似的。
然而,对于更复杂的数学运算,内部使用浮点算术,如果中间步骤不转换为与输入和输出相同宽度的定点格式,可以获得更精确的结果。例如,(10::FLOAT / 3::FLOAT)::FLOAT * 3 = 10
而 (10::DECIMAL(18, 3) / 3::DECIMAL(18, 3))::DECIMAL(18, 3) * 3 = 9.999
。
一般来说,我们建议:
- 如果您需要精确存储已知小数位数的数字,并且需要精确的加法、减法和乘法(例如用于货币金额),请使用
DECIMAL
数据类型或其NUMERIC
别名。 - 如果您想进行快速或复杂的计算,浮点数据类型可能更合适。然而,如果您将结果用于任何重要的事情,您应该仔细评估您的实现,以处理可能不同于您预期的角落情况(范围、无穷大、下溢、无效操作),并且您应该熟悉常见的浮点陷阱。文章“每个计算机科学家都应该知道的浮点算术”由David Goldberg撰写和Bruce Dawson博客上的浮点系列提供了极好的起点。
在大多数平台上,FLOAT
类型的范围至少为 1E-37 到 1E+37,精度至少为 6 位小数。DOUBLE
类型的范围通常为 1E-307 到 1E+308,精度至少为 15 位。超出这些范围的正数(以及超出镜像范围的负数)在某些平台上可能会导致错误,但通常会分别转换为零或无穷大。
除了普通的数值外,浮点类型还有几个特殊值,代表IEEE 754的特殊值:
Infinity
: 无穷大-Infinity
: 负无穷大NaN
: 不是一个数字
在具有所需CPU/FPU支持的机器上,DuckDB遵循IEEE 754规范处理这些特殊值,但有两个例外:
NaN
与NaN
比较相等,并且大于任何其他浮点数。- 一些浮点函数,如
sqrt
/sin
/asin
对于超出其定义范围的值会抛出错误,而不是返回NaN
。
要在SQL命令中将这些值作为字面量插入,您必须在它们周围加上引号,您可以将Infinity
缩写为Inf
,并且您可以使用任何大小写。例如:
SELECT
sqrt(2) > '-inf',
'nan' > sqrt(2)
(sqrt(2) > '-inf') | ('nan' > sqrt(2)) |
---|---|
true | true |
通用唯一标识符 (UUID
s)
DuckDB 通过 UUID
类型支持通用唯一标识符(UUIDs)。这些标识符使用 128 位,并在内部表示为 HUGEINT
值。
当打印时,它们以小写十六进制字符显示,并用破折号分隔,如下所示:⟨8 字符⟩-⟨4 字符⟩-⟨4 字符⟩-⟨4 字符⟩-⟨12 字符⟩
(总共使用 36 个字符,包括破折号)。例如,4ac7a9e9-607c-4c8a-84f3-843f0191e3fd
是一个有效的 UUID。
要生成一个新的UUID,请使用uuid()
实用函数。