文章目录
Flink SQL 有丰富的native数据类型。
Data Type
数据类型描述表生态系统中值的逻辑类型。它可用于声明输入和/或输出类型的操作。
Flink 的数据类型类似于 SQL 标准的数据类型术语,但也包含有关有效处理标量表达式的值的可空性的信息。
比如:
- INT
- INT NOT NULL
- INTERVAL DAY TO SECOND(3)
- ROW<myField ARRAY, myOtherField TIMESTAMP(3)>
可以在下面找到所有预定义数据类型的列表。
Table API中的所有数据类型(Data Types)
基于 JVM 的 API 的用户在表 API 中使用 org.apache.flink.table.types.DataType 的实例,或者在定义连接器、目录或用户定义的函数时使用。
数据类型实例有两个职责:
- 逻辑类型的声明,它并不意味着传输或存储的具体物理表示,而是定义了基于JVM/ Python语言和表生态系统之间的边界。
- 可选:向计划程序提供有关数据的物理表示的提示,这在边缘对其他 API 非常有用。
对于基于JVM的语言,所有预定义的数据类型都可以在org.apache.flink.table.api.DataTypes中找到。
建议在表程序中添加星形导入(import org.apache.flink.table.api.DataTypes.*),以获得流畅的 API:
import static org.apache.flink.table.api.DataTypes.*;
DataType t = INTERVAL(DAY(), SECOND(3));
Data Types列表
Data Type | Remarks for Data Type(备注) |
---|---|
CHAR | |
VARCHAR | |
STRING | |
BOOLEAN | |
BINARY | |
VARBINARY | |
BYTES | |
DECIMAL | 支持固定精度和刻度。 |
TINYINT | |
SMALLINT | |
INTEGER | |
BIGINT | |
FLOAT | |
DOUBLE | |
DATE | |
TIME | 仅支持精度 0。 |
TIMESTAMP | |
TIMESTAMP_LTZ | |
INTERVAL | |
ARRAY | |
MULTISET | |
MAP | |
ROW | |
RAW | |
Structured types | 仅在用户定义函数中公开。 |
Character Strings
CHAR
固定长度字符串的数据类型。
CHAR
CHAR(n)
可以使用 CHAR(n) 声明类型,其中 n 是码位数。n 的值必须介于 1 和 2,147,483,647 之间(包括 1 和 2,147,483,647)。如果未指定长度,则 n 等于 1。
VARCHAR / STRING
可变长度字符串的数据类型。
VARCHAR
VARCHAR(n)
STRING
可以使用 VARCHAR(n) 声明类型,其中 n 是最大码位数。n 的值必须介于 1 和 2,147,483,647 之间(包括 1 和 2,147,483,647)。如果未指定长度,则 n 等于 1。
STRING 是 VARCHAR(2147483647) 的同义词。
Binary Strings
BINARY
固定长度二进制字符串的数据类型(= 字节序列)
BINARY
BINARY(n)
可以使用 BINARY(n) 声明类型,其中 n 是字节数。n 的值必须介于 1 和 2,147,483,647 之间(包括 1 和 2,147,483,647)。如果未指定长度,则 n 等于 1。
VARBINARY / BYTES
可变长度二进制字符串的数据类型(= 字节序列)。
VARBINARY
VARBINARY(n)
BYTES
可以使用 VARBINARY(n) 声明类型,其中 n 是最大字节数。n 的值必须介于 1 和 2,147,483,647 之间(包括 1 和 2,147,483,647)。如果未指定长度,则 n 等于 1。
BYTES VARBINARY(2147483647)的同义词.
Exact Numerics
DECIMAL
具有固定精度和小数位数的十进制数的数据类型。
DECIMAL
DECIMAL(p)
DECIMAL(p, s)
DEC
DEC(p)
DEC(p, s)
NUMERIC
NUMERIC(p)
NUMERIC(p, s)
可以使用 DECIMAL(p, s) 声明类型,其中 p 是数字(精度)中的位数,s 是数字(小数位数)中小数点右边的位数(小数位数)。p 的值必须介于 1 和 38 之间(包括 1 和 38)。s 的值必须介于 0 和 p 之间(包括 0 和 p)。p 的默认值为 10。s 的默认值为 0。
NUMERIC(p, s) 和 DEC(p, s) 是此类型的同义词。
TINYINT
值为 -128 到 127 的 1 字节有符号整数的数据类型。
TINYINT
SMALLINT
值为 -32,768 到 32,767 的 2 字节有符号整数的数据类型。
SMALLINT
INT
值为 -2,147,483,648 到 2,147,483,647 的 4 字节有符号整数的数据类型。
INT
INTEGER
INTEGER 是此类型的同义词。
BIGINT
值为 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 的 8 字节有符号整数的数据类型。
BIGINT
Approximate Numerics (浮点数字)
FLOAT
4 字节单精度浮点数的数据类型。
与SQL标准相比,该类型不采用参数。
FLOAT
DOUBLE
DOUBLE
DOUBLE PRECISION
8 字节双精度浮点数的数据类型。
双精度是此类型的同义词。
Date and Time
DATE
由年-月-日组成的日期的数据类型,其值范围从 0000-01-01 到 9999-12-31。
与 SQL 标准相比,范围从 0000 年开始。
DATE
TIME
不带时区的时间的数据类型,由小时:分钟:秒[.小数]组成,精度最高为纳秒,值范围为 00:00:00.000000000 到 23:59:59.9999999999。
与SQL标准相比,不支持闰秒(23:59:60和23:59:61),因为语义更接近java.time.LocalTime。未提供带时区的时间。
TIME
TIME(p)
可以使用 TIME(p) 声明类型,其中 p 是小数秒(精度)的位数。p 的值必须介于 0 和 9 之间(包括 0 和 9)。如果未指定精度,则 p 等于 0。
TIMESTAMP
不带时区的时间戳的数据类型,由年-月-日小时:分钟:秒[.分数] 组成,精度高达纳秒,值范围为 0000-01-01 00:00:00.000000000 到 9999-12-31 23:59:59.9999999999。
TIMESTAMP
TIMESTAMP(p)
TIMESTAMP WITHOUT TIME ZONE
TIMESTAMP(p) WITHOUT TIME ZONE
可以使用 TIMESTAMP(p) 声明该类型,其中 p 是小数秒(精度)的位数。p 的值必须介于 0 和 9 之间(包括 0 和 9)。如果未指定精度,则 p 等于 6。
不带时区的时间戳(p)是此类型的同义词。
TIMESTAMP WITH TIME ZONE
时间戳的数据类型,其时区由年-月-日小时:分钟:秒[.小数]区域组成,精度最高为纳秒,值范围为 0000-01-01 00:00:00.000000000 +14:59 到 9999-12-31 23:59:59.999999999 -14:59。
与TIMESTAMP_LTZ相比,时区偏移信息以物理方式存储在每个基准面中。它单独用于每个计算,可视化或与外部系统的通信。
TIMESTAMP WITH TIME ZONE
TIMESTAMP(p) WITH TIME ZONE
TIMESTAMP_LTZ
具有本地时区的时间戳的数据类型,该时间戳由年-月-日小时:分钟:秒[.分数] 区域组成,精度最高为纳秒,值范围为 0000-01-01 00:00:00.000000000 +14:59 到 9999-12-31 23:59:59.999999999 -14:59。
不支持闰秒(23:59:60 和 23:59:61)。
与带时区的时间戳相比,时区偏移信息不会以物理方式存储在每个基准面中。每个数据都按照当前会话中配置的本地时区进行解释,以便进行计算和可视化。
此类型允许根据配置的会话时区解释 UTC 时间戳,从而填补无时区和时区强制时间戳类型之间的空白。
TIMESTAMP_LTZ
TIMESTAMP_LTZ(p)
TIMESTAMP WITH LOCAL TIME ZONE
TIMESTAMP(p) WITH LOCAL TIME ZONE
可以使用 TIMESTAMP_LTZ(p) 声明类型,其中 p 是小数秒(精度)的位数。p 的值必须介于 0 和 9 之间(包括 0 和 9)。如果未指定精度,则 p 等于 6。
带有本地时区的时间戳(p)是此类型的同义词。
INTERVAL YEAR TO MONTH
一组年月间隔类型的数据类型。
必须将类型参数化为以下解决方法之一:
- 年间隔,
- 间隔数年到数月,
- 或月的间隔。
年月间隔由 +年-月组成,其值范围从 -9999-11 到 +9999-11。
对于所有类型的分辨率,值表示形式都是相同的。例如,50 的月间隔始终以年到月间隔格式表示(默认年份精度为 +04-02)。
INTERVAL YEAR
INTERVAL YEAR(p)
INTERVAL YEAR(p) TO MONTH
INTERVAL MONTH
可以使用上述组合声明类型,其中 p 是年位数(年精度)。p 的值必须介于 1 和 4 之间(包括 1 和 4)。如果未指定年份精度,则 p 等于 2。
INTERVAL DAY TO SECOND
一组日时间间隔类型的数据类型。
必须将类型参数化为以下分辨率之一,精度最高可达纳秒:
interval of days,
interval of days to hours,
interval of days to minutes,
interval of days to seconds,
interval of hours,
interval of hours to minutes,
interval of hours to seconds,
interval of minutes,
interval of minutes to seconds,
or interval of seconds.
日-时间间隔由 +天小时:月:秒.小数组成,值范围从 -999999 23:59:59.999999999 到 +999999 23:59:59.999999999。对于所有类型的分辨率,值表示形式都是相同的。例如,秒的间隔 70 始终以天到秒间隔格式表示(使用默认精度):+00 00:01:10.000000。
INTERVAL DAY
INTERVAL DAY(p1)
INTERVAL DAY(p1) TO HOUR
INTERVAL DAY(p1) TO MINUTE
INTERVAL DAY(p1) TO SECOND(p2)
INTERVAL HOUR
INTERVAL HOUR TO MINUTE
INTERVAL HOUR TO SECOND(p2)
INTERVAL MINUTE
INTERVAL MINUTE TO SECOND(p2)
INTERVAL SECOND
INTERVAL SECOND(p2)
可以使用上述组合声明类型,其中 p1 是天数(日精度),p2 是小数秒的位数(小数精度)。p1 的值必须介于 1 和 6 之间(包括 1 和 6)。p2 的值必须介于 0 和 9 之间(包括 0 和 9)。如果未指定 p1,则默认情况下它等于 2。如果未指定 p2,则默认情况下它等于 6。
Constructured Data Types
ARRAY
具有相同子类型的元素数组的数据类型。
与 SQL 标准相比,数组的最大基数无法指定,但固定为 2,147,483,647。此外,支持将任何有效类型作为子类型。
ARRAY<t>
t ARRAY
可以使用 ARRAY 声明类型,其中 t 是所包含元素的数据类型。
t ARRAY 是更接近 SQL 标准的同义词。例如,INT ARRAY 等效于 ARRAY。
MAP
将键(包括 NULL)映射到值(包括 NULL)的关联数组的数据类型。映射不能包含重复的键;每个键最多可以映射到一个值。
元素类型没有限制;用户有责任确保独特性。
映射类型是 SQL 标准的扩展。
MAP<kt, vt>
可以使用 MAP<kt、 vt>声明类型,其中 kt 是键元素的数据类型,vt 是值元素的数据类型。
MULTISET
多集的数据类型(=包)。与集合不同,它允许其具有通用子类型的每个元素具有多个实例。每个唯一值(包括 NULL)都映射到某个多重性。
元素类型没有限制;用户有责任确保独特性。
MULTISET<t>
t MULTISET
可以使用 MULTISET 声明类型,其中 t 是所包含元素的数据类型。
multiset 是更接近 SQL 标准的同义词。例如,INT MULTISET 等效于 MULTISET。
ROW
字段序列的数据类型。
字段由字段名称、字段类型和可选描述组成。表中一行最具体的类型是行类型。在这种情况下,行的每一列都对应于与该列具有相同序号位置的行类型的字段。
与 SQL 标准相比,可选字段描述简化了复杂结构的处理。
行类型类似于从其他不符合标准的框架中已知的 STRUCT 类型。
ROW<n0 t0, n1 t1, ...>
ROW<n0 t0 'd0', n1 t1 'd1', ...>
ROW(n0 t0, n1 t1, ...>
ROW(n0 t0 'd0', n1 t1 'd1', ...)
可以使用 ROW<n0 t0 ‘d0’, n1 t1 ‘d1’, …> 其中 n 是字段的唯一名称,t 是字段的逻辑类型,d 是字段的描述。
ROW(…) 是更接近 SQL 标准的同义词。例如,ROW(myField INT,myOtherField BOOLEAN)等效于ROW<myField INT,myOtherField BOOLEAN>。
User-Defined Data Types
Other Data Types
BOOLEAN
具有(可能)TRUE、FALSE 和 UNKNOWN 三值逻辑的布尔值的数据类型。
RAW
任意序列化类型的数据类型。此类型是表生态系统中的黑匣子,仅在边缘反序列化。
原始类型是 SQL 标准的扩展。
RAW('class', 'snapshot')
NULL
用于表示非类型化 NULL 值的数据类型。
空类型是 SQL 标准的扩展。空类型除了 NULL 之外没有其他值,因此,它可以被强制转换为任何类似于 JVM 语义的可空类型。
此类型有助于在使用 NULL 文本的 API 调用中表示未知类型,以及桥接到定义此类类型的格式(如 JSON 或 Avro)。
这种类型在实践中不是很有用,只是为了完整起见,这里只是提到它。
CAST 方法
Flink Table API 和 Flink SQL 支持从 输入 数据类型 到 目标 数据类型的转换。有的转换 无论输入值是什么都能保证转换成功,而有些转换则会在运行时失败(即不可能转换为 目标 数据类型对应的值)。 例如,将 INT 数据类型的值转换为 STRING 数据类型一定能转换成功,但无法保证将 STRING 数据类型转换为 INT 数据类型。
在生成执行计划时,Flink 的 SQL 检查器会拒绝提交那些不可能直接转换为 目标 数据类型的SQL,并抛出 ValidationException 异常, 例如从 TIMESTAMP 类型转化到 INTERVAL 类型。 然而有些查询即使通过了 SQL 检查器的验证,依旧可能会在运行期间转换失败,这就需要用户正确处理这些失败了。
在 Flink Table API 和 Flink SQL 中,可以用下面两个内置方法来进行转换操作:
- CAST:定义在 SQL 标准的 CAST 方法。在某些容易发生转换失败的查询场景中,当实际输入数据不合法时,作业便会运行失败。类型推导会保留输入类型的可空性。
- TRY_CAST:常规 CAST 方法的扩展,当转换失败时返回 NULL。该方法的返回值允许为空。
例如:
CAST('42' AS INT) --- 结果返回数字 42 的 INT 格式(非空)
CAST(NULL AS VARCHAR) --- 结果返回 VARCHAR 类型的空值
CAST('non-number' AS INT) --- 抛出异常,并停止作业
TRY_CAST('42' AS INT) --- 结果返回数字 42 的 INT 格式
TRY_CAST(NULL AS VARCHAR) --- 结果返回 VARCHAR 类型的空值
TRY_CAST('non-number' AS INT) --- 结果返回 INT 类型的空值
COALESCE(TRY_CAST('non-number' AS INT), 0) --- 结果返回数字 0 的 INT 格式(非空)
下表展示了各个类型的转换程度,“Y” 表示支持,“!” 表示转换可能会失败,“N” 表示不支持:
备注:
所有转化到具有固长或变长的类型时会根据类型的定义来裁剪或填充数据。
使用 TO_TIMESTAMP 方法和 TO_TIMESTAMP_LTZ 方法的场景,不要使用 CAST 或 TRY_CAST。
支持转换,当且仅当用其内部数据结构也支持转化时。转换可能会失败,当且仅当用其内部数据结构也可能会转换失败。
支持转换,当且仅当用使用 RAW 的类和类的序列化器一样。
支持转换,当且仅当用使用 INTERVAL 做“月”到“年”的转换。
支持转换,当且仅当用使用 INTERVAL 做“天”到“时间”的转换。
请注意:无论是 CAST 还是 TRY_CAST,当输入为 NULL ,输出也为 NULL。
数据类型提取
在 API 中的许多位置,Flink 尝试使用反射从类信息中自动提取数据类型,以避免重复的手动模式工作。但是,以反射方式提取数据类型并不总是成功的,因为可能缺少逻辑信息。因此,可能需要在类或字段声明附近添加其他信息以支持提取逻辑。
下表列出了可以隐式映射到数据类型的类,而无需进一步的信息。
如果你打算在Scala中实现类,建议使用盒装类型(例如.java.lang.Integer)而不是Scala的原语。Scala的基元(例如Int或Double)被编译为JVM原语(例如int/double),并产生NOT NULL语义,如下表所示。
此外,泛型中使用的 Scala 原语(例如.java.util.Map[Int, Double])在编译过程中被擦除,并导致类信息类似于 java.util.Map[java.lang.Object, java.lang.Object]。
Class | Data Type |
---|---|
java.lang.String | STRING |
java.lang.Boolean | BOOLEAN |
boolean | BOOLEAN NOT NULL |
java.lang.Byte | TINYINT |
byte | TINYINT NOT NULL |
java.lang.Short | SMALLINT |
short | SMALLINT NOT NULL |
java.lang.Integer | INT |
int | INT NOT NULL |
java.lang.Long | BIGINT |
long | BIGINT NOT NULL |
java.lang.Float | FLOAT |
float | FLOAT NOT NULL |
java.lang.Double | DOUBLE |
double | DOUBLE NOT NULL |
java.sql.Date | DATE |
java.time.LocalDate | DATE |
java.sql.Time | TIME(0) |
java.time.LocalTime | TIME(9) |
java.sql.Timestamp | TIMESTAMP(9) |
java.time.LocalDateTime | TIMESTAMP(9) |
java.time.OffsetDateTime | TIMESTAMP(9) WITH TIME ZONE |
java.time.Instant | TIMESTAMP_LTZ(9) |
java.time.Duration | INTERVAL SECOND(9) |
java.time.Period | INTERVAL YEAR(4) TO MONTH |
byte[] | BYTES |
T[] | ARRAY |
java.util.Map<K, V> | MAP<K, V> |
structured type T | anonymous structured type T |
本文档中提到的其他 JVM 桥接类需要@DataTypeHint注释。
数据类型提示可以参数化或替换单个函数参数和返回类型、结构化类或结构化类字段的默认提取逻辑。实现者可以通过声明@DataTypeHint注释来选择应在多大程度上修改默认提取逻辑。
@DataTypeHint注释提供一组可选的提示参数。以下示例中显示了其中一些参数。有关详细信息,请参阅注释类的文档。