1. 版本说明
本文档内容基于
flink-1.13.x
,其他版本的整理,请查看本人博客的 flink 专栏其他文章。
2. 介绍
Flink SQL有一组丰富的本地数据类型可供用户使用。
数据类型描述表生态系统中值的逻辑类型,它可用于声明操作的输入和/或输出类型。
Flink的数据类型类似于SQL标准的数据类型,但也包含了关于值是否为空的信息,以便有效地处理标量表达式。
数据类型的例子有:
- INT
- INT NOT NULL
- INTERVAL DAY TO SECOND(3)
ROW<myField ARRAY<BOOLEAN>, myOtherField TIMESTAMP(3)>
所有预定义的数据类型在下面列出。
2.1. Table API 中的数据类型
java/scala:
基于 JVM 的用户,在使用 Table API 或者是自定义连接器、catalog、自定义函数时,可以使用
org.apache.flink.table.types.DataType
类的实例。
DataType
实例有两个职责:
- 声明一个逻辑类型:这并不是定义传输或存储的具体物理表示,但其定义了基于 jvm/Python 语言和表生态系统之间的边界。
- 可选:将数据的物理表示提示给 planner 计划器,这对于其他 API 是非常有用的。
为了流畅的使用 API ,可以在表程序开头添加
import
语句导入所有的数据类型。
java
importstaticorg.apache.flink.table.api.DataTypes.*;DataType t =INTERVAL(DAY(),SECOND(3));
scala
importorg.apache.flink.table.api.DataTypes._
val t: DataType = INTERVAL(DAY(), SECOND(3));
2.1.1. 物理提示
基于sql的类型系统末端的表生态系统边缘需要物理提示,并且是编程代码指定的数据类型。提示表示所期望的数据格式。
例如,数据源使用
java.sql.Timestamp
类来生成逻辑时间戳值,而不是使用
java.time.LocalDateTime
,后者是默认值。有了这些信息,程序运行时就可以将生成的类转换为它的内部数据格式。同时,sink 也可以声明它从运行时获取到的数据格式。
下面是一些如何声明桥接转换类的例子:
java
// 告诉运行时使用 java.sql.Timestamp 而不是 java.time.LocalDateTime 实例DataType t =DataTypes.TIMESTAMP(3).bridgedTo(java.sql.Timestamp.class);// 告诉运行时使用原生的 int 数组而不是包装的 integer 数组DataType t =DataTypes.ARRAY(DataTypes.INT().notNull()).bridgedTo(int[].class);
scala
// 告诉运行时使用 java.sql.Timestamp 而不是 java.time.LocalDateTime 实例val t: DataType = DataTypes.TIMESTAMP(3).bridgedTo(classOf[java.sql.Timestamp]);// 告诉运行时使用原生的 int 数组而不是包装的 integer 数组val t: DataType = DataTypes.ARRAY(DataTypes.INT().notNull()).bridgedTo(classOf[Array[Int]]);
注意:通常来说,只有在扩展 API 时才要求物理提示。用户在自定义 sources/sinks/functions 时并不需要定义这些提示。表程序中的提示(比如:
field.cast(TIMESTAMP(3).bridgedTo(Timestamp.class))
)将会被忽略。
下面将列出所有预定义数据类型。
默认的计划器支持下面的SQL类型
java/scala
数据类型解释CHARVARCHARSTRINGBOOLEANBYTES现在还不支持BINARY 和VARBINARYDECIMAL支持固定的精度和刻度TINYINTSMALLINTINTEGERBIGINTFLOATDOUBLEDATETIME只支持精度:0TIMESTAMPTIMESTAMP_LTZINTERVAL只支持interval of MONTH 和SECOND(3)ARRAYMULTISETMAPROWRAWstructured types目前仅可在自定义函数中使用
3. 列出所有数据类型
该章节会列出所有预定义的数据类型。
java/scala
对于基于 JVM 的 Table API ,在
org.apache.flink.table.api.DataTypes
中的类型都已经可以使用了。
3.1. Character Strings
3.1.1. CHAR
固定长度的character string。
SQL
CHARCHAR(n)
java/scala
DataTypes.CHAR(n);
桥接到JVM数据类型
Java 类型InputOutputOutputjava.lang.StringXX默认byte[]XXUTF-8编码org.apache.flink.table.data.StringDataXX内部数据结构
该类型可以使用
CHAR(n)
声明,其中
n
是字符的数量。
n
的值必须在
1
和
2147,483,647
之间(前后都包括)。如果没有指定长度,则
n
等于1。
3.1.2. VARCHAR/STRING
可变长度的character string。
SQL
VARCHARVARCHAR(n)
STRING
java/scala
DataTypes.VARCHAR(n);DataTypes.STRING();
桥接到JVM数据类型
Java 类型InputOutputOutputjava.lang.StringX默认byte[]XXUTF-8编码org.apache.flink.table.data.StringDataXX内部数据结构
该类型可以使用
VARCHAR(n)
声明,其中
n
是最大的字符数量。
N
的值必须在
1
和
2147,483,647
之间(包括两者)。如果没有指定长度,则
n
等于1。
STRING
和
VARCHAR(2147483647)
相同。
3.2. Binary Strings
BINARY
固定长度的二进制字符串,等同于字节序列。
SQL
BINARYBINARY(n)
java/scala
DataTypes.BINARY(n);
桥接到JVM数据类型
Java 类型InputOutputOutputbyte[]XX默认
该类型可以使用
BINARY(n)
声明,其中
n
为字节数。
N
的值必须在
1
和
2147,483,647
之间(包括两者)。如果没有指定长度,则
n
等于1。
3.2.1. VARBINARY/BYTES
可变长度的二进制字符串,等同于字节序列。
SQL
VARBINARYVARBINARY(n)
BYTES
java/scala
DataTypes.VARBINARY(n);DataTypes.BYTES();
桥接到JVM数据类型
Java 类型InputOutputOutputbyte[]XX默认
该类型可以使用
VARBINARY(n)
声明,其中
n
为最大字节数。
N
的值必须在
1
和
2147,483,647
之间(包括两者)。如果没有指定长度,则
n
等于1。
BYTES
和
VARBINARY(2147483647)
相同。
3.3. 精确数字
3.3.1. DECIMAL
具有固定精度和比例的小数的数据类型。
SQL
DECIMALDECIMAL(p)DECIMAL(p, s)DECDEC(p)DEC(p, s)NUMERICNUMERIC(p)NUMERIC(p, s)
java/scala
DataTypes.DECIMAL(p,s);
桥接到JVM数据类型
Java 类型InputOutputOutputjava.math.BigDecimalXX默认org.apache.flink.table.data.DecimalDataXX内部数据结构
该类型可以使用
DECIMAL(p, s)
声明,其中
p
是数字(精度)的总位数,
s
是数字(刻度)小数点右边的位数。
P
的值必须在
1
和
38
之间(包括两者)。
S
的值必须在
0
和
p
之间(包括两者)。
p
的默认值是10。
s
的默认值是0。
NUMERIC(p, s)
、
DEC(p, s)
和该类型含义一样。
3.3.2. TINYINT
值从
-128
到
127
,1个字节,有符号整数。
SQL
TINYINT
java/scala
DataTypes.TINYINT();
桥接到JVM数据类型
Java 类型InputOutputOutputjava.lang.ByteXX默认byteX(X)类型为非空null时才会输出
3.3.3. SMALLINT
值从
-32,768
到
32,767
,2个字节,有符号整数。
SQL
SMALLINT
java/scala
DataTypes.SMALLINT();
桥接到JVM数据类型
Java 类型InputOutputOutputjava.lang.ShortXX默认shortX(X)类型为非空null时才会输出
3.3.4. INT
值从
-2147,483,648
到
2147,483,647
,4个字节,有符号整数。
SQL
INTINTEGER
java/scala
DataTypes.INT();
桥接到JVM数据类型
Java 类型InputOutputOutputjava.lang.IntegerXX默认intX(X)类型为非空null时才会输出
INTEGER也表示该类型。
3.3.5. BIGINT
值从
-9,223,372,036,854,775,808
到
9,223,372,036,854,775,807
,8个字节,有符号整数。
SQL
BIGINT
java/scala
DataTypes.BIGINT();
桥接到JVM数据类型
Java 类型InputOutputOutputjava.lang.LongXX默认longX(X)类型为非空null时才会输出
3.4. 近似数字
3.4.1. FLOAT
4个字节的单精度浮点数。
与SQL标准相比,该类型不带参数。
SQL
FLOAT
java/scala
DataTypes.FLOAT();
桥接到JVM数据类型
Java 类型InputOutputOutputjava.lang.FloatXX默认floatX(X)类型为非空null时才会输出
3.4.2. DOUBLE
8字节的双精度浮点数。
SQL
DOUBLEDOUBLEPRECISION
java/scala
DataTypes.DOUBLE();
桥接到JVM数据类型
Java 类型InputOutputOutputjava.lang.DoubleXX默认doubleX(X)类型为非空null时才会输出
DOUBLE PRECISION
也表示该类型。
3.5. Date 和Time
注意:所有时间类型的精度 p 指的都是秒后面的小数个数。
3.5.1. DATE
日期数据类型为
年-月-日
,取值范围为
0000-01-01 ~ 9999-12-31
。
与 SQL 标准相比,范围从 0000 年开始。
SQL
DATE
java/scala
DataTypes.DATE();
桥接到JVM数据类型
Java 类型InputOutputOutputjava.time.LocalDateXX默认java.sql.DateXXjava.lang.IntegerXX描述从纪元开始经过的天数intX(X)描述从纪元开始已经过的天数。类型为非空null时才会输出
3.5.2. TIME
无时区的时间数据类型,由
时:分:秒[.小数]
组成,精度可达纳秒,值范围从
00:00:00.000000000
到
23:59:59.999999999
。
SQL/Java/Scala
与SQL标准相比,该类型不支持闰秒
(23:59:60和23:59:61)
,因为该类型语义更接近
java.time.LocalTime
。目前不支持带时区的时间。
SQL
TIMETIME(p)
java/scala
DataTypes.TIME(p);
桥接到JVM数据类型
Java 类型InputOutputOutputjava.time.LocalTimeXX默认java.sql.TimeXXjava.lang.IntegerXX描述当天经过的毫秒值intX(X)描述当天经过的毫秒值
类型为非空null时才会输出java.lang.LongXX描述当天经过的纳秒值long(X)描述当天经过的纳秒值
类型为非空null时才会输出
该类型可以使用
TIME(p)
声明,其中p是秒后面小数的位数(精度)。P必须有一个介于0和9之间的值(包括两者)。如果没有指定精度,p等于0。
3.5.3. TIMESTAMP
无时区的时间戳数据类型,由
年-月-日 时:分:秒[.小数]
组成,精度可达纳秒,值范围从
0000-01-01 00:00:00.000000000
到
9999-12-31 23:59:59.99999999999
。
SQL/Java/Scala
与SQL标准相比,该类型不支持闰秒(23:59:60和23:59:61),因为该类型语义更接近
java.time.LocalDateTime
。
不支持从
BIGINT
(JVM long类型)转化为该类型,也不支持从该类型转换到
BIGINT
(JVM long类型),因为这种转换需要时区,但是该类型是不受时区限制的。
如果需要使用到时区,则可以使用
TIMESTAMP_LTZ
类型。
SQL
TIMESTAMPTIMESTAMP(p)TIMESTAMP WITHOUT TIME ZONE
TIMESTAMP(p) WITHOUT TIME ZONE
java/scala
DataTypes.TIMESTAMP(p);
桥接到JVM数据类型
Java 类型InputOutputOutputjava.time.LocalDateTimeXX默认java.sql.TimestampXXorg.apache.flink.table.data.TimestampDataXX内部数据结构
该类型可以使用
TIMESTAMP(p)
声明,其中p是秒后面小数(精度)的位数。P必须是一个介于0和9之间的值(包括两者)。如果没有指定精度,则p等于6。
TIMESTAMP(p) WITHOUT TIME ZONE
也表示该类型。
3.5.4. TIMESTAMP WITH TIME ZONE
有时区的时间戳的数据类型,由
年-月-日 时:分:秒[.分数]
组成,精确度可达纳秒,值范围为
0000-01-01 00:00:00.000000000 +14:59
到
9999-12-31 23:59:59.999999999 -14:59
。
与
TIMESTAMP_LTZ
相比,时区偏移信息物理地存储在每个数据中。它被单独用于每一个计算、可视化以及与外部系统通信。
SQL
TIMESTAMPWITHTIME ZONE
TIMESTAMP(p)WITHTIME ZONE
java/scala
DataTypes.TIMESTAMP_WITH_TIME_ZONE(p);
桥接到JVM数据类型
Java 类型InputOutputOutputjava.time.OffsetDateTimeXX默认java.time.ZonedDateTimeX忽略时区ID
3.5.5. TIMESTAMP_LTZ
使用本地时区的时间戳数据类型,由
年-月-日 时:分:秒[.分数]
组成,精度可达纳秒,值范围为
0000-01-01 00:00:00.000000000 +14:59
到
9999-12-31 23:59:59.999999999 -14:59
。
该类型允许根据配置的会话时区解释UTC时间戳来填补自由时区和强制时区时间戳类型之间的空白。
SQL
TIMESTAMP_LTZ
TIMESTAMP_LTZ(p)TIMESTAMPWITHLOCALTIME ZONE
TIMESTAMP(p)WITHLOCALTIME ZONE
java/scala
DataTypes.TIMESTAMP_LTZ(p);DataTypes.TIMESTAMP_WITH_LOCAL_TIME_ZONE(p);
桥接到JVM数据类型
Java 类型InputOutputOutputjava.time.InstantXX默认java.lang.IntegerXX描述从纪元开始经过的秒数intX(X)描述从纪元开始经过的秒数
类型为非空null时才会输出java.lang.LongXX描述从纪元开始经过的毫秒数longX(X)描述从纪元开始经过的毫秒数
类型为非空null时才会输出java.sql.TimestampXX描述从纪元开始经过的毫秒数org.apache.flink.table.data.TimestampDataXX内部数据结构
可以使用
TIMESTAMP_LTZ(p)
声明该类型,其中p是秒后面小数(精度)的位数。P必须是一个介于0和9之间的值(包括两者)。如果没有指定精度,则p等于6。
TIMESTAMP(p) WITH LOCAL TIME ZONE
是该类型的同义词。
3.5.6. INTERVAL YEAR TO MONTH
一组年-月间隔类型的数据类型。
该类型必须参数化为以下解析之一:
- interval of years
- interval of years to months
- interval of months
年-月
的间隔由
+year-momth
组成,取值范围为
-9999-11
~
+9999-11
。
比如,50个月的间隔以年到月的间隔格式表示为(使用默认的年精度):
+04-02
。
SQL
INTERVALYEARINTERVALYEAR(p)INTERVALYEAR(p)TOMONTHINTERVALMONTH
java/scala
DataTypes.INTERVAL(DataTypes.YEAR());DataTypes.INTERVAL(DataTypes.YEAR(p));DataTypes.INTERVAL(DataTypes.YEAR(p),DataTypes.MONTH());DataTypes.INTERVAL(DataTypes.MONTH());
桥接到JVM数据类型
Java 类型InputOutputOutputjava.time.PeriodXX忽略天的部分,默认java.lang.IntegerXX描述经过的月数intX(X)描述经过的月数
类型为非空null时才会输出
可以使用上面的组合声明类型,其中p是年份的位数(年份精度)。P的值必须在1和4之间(包括两者)。如果没有指定年份精度,则p等于2。
3.5.7. 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
- interval of seconds
day-time
的间隔由
+天 时:分:秒.小数
组成,取值范围为
-999999 23:59:59.999999999
到
+999999 23:59:59.999999999
。
例如,70秒的间隔以天到秒的间隔格式表示(具有默认精度):
+00 00:01:10 000000
。
SQL
INTERVALDAYINTERVALDAY(p1)INTERVALDAY(p1)TOHOURINTERVALDAY(p1)TOMINUTEINTERVALDAY(p1)TOSECOND(p2)INTERVALHOURINTERVALHOURTOMINUTEINTERVALHOURTOSECOND(p2)INTERVALMINUTEINTERVALMINUTETOSECOND(p2)INTERVALSECONDINTERVALSECOND(p2)
java/scala
DataTypes.INTERVAL(DataTypes.DAY());DataTypes.INTERVAL(DataTypes.DAY(p1));DataTypes.INTERVAL(DataTypes.DAY(p1),DataTypes.HOUR());DataTypes.INTERVAL(DataTypes.DAY(p1),DataTypes.MINUTE());DataTypes.INTERVAL(DataTypes.DAY(p1),DataTypes.SECOND(p2));DataTypes.INTERVAL(DataTypes.HOUR());DataTypes.INTERVAL(DataTypes.HOUR(),DataTypes.MINUTE());DataTypes.INTERVAL(DataTypes.HOUR(),DataTypes.SECOND(p2));DataTypes.INTERVAL(DataTypes.MINUTE());DataTypes.INTERVAL(DataTypes.MINUTE(),DataTypes.SECOND(p2));DataTypes.INTERVAL(DataTypes.SECOND());DataTypes.INTERVAL(DataTypes.SECOND(p2));
桥接到JVM数据类型
Java 类型InputOutputOutputjava.time.DurationXX默认java.lang.LongXX描述毫秒值longX(X)描述毫秒值
类型为非空null时才会输出
可以使用上面的组合声明该类型,其中
p1
是天数(天数精度),
p2
是小数秒(小数精度)。
P1
的值必须在1到6之间(包括1和6)。
P2
的值必须在0到9之间(包括两者)。
如果没有指定p1,默认值为2。如果没有指定p2,默认值为6。
3.6. Constructed结构数据类型
3.6.1. ARRAY
具有相同子类型元素的数组。
与SQL标准相比,不能指定数组的最大基数,而是固定在
2,147,483,647
。此外,支持任何有效类型作为子类型。
SQL
ARRAY<t>
t ARRAY
java/scala
DataTypes.ARRAY(t);
桥接到JVM数据类型
Java 类型InputOutputOutputt(X)由子类型决定,默认
java.util.List<t>
XX
java.util.List<t>
的子类Xorg.apache.flink.table.data.ArrayDataXX内部数据结构
该类型可以使用
ARRAY<t>
声明,其中
t
是所包含元素的数据类型。
t ARRAY
是接近SQL标准的同义词。例如,
INT ARRAY
等价于
ARRAY<INT>
。
3.6.2. MAP
关联数组的数据类型,将键(包括NULL)映射到值(包括NULL)。
map
不能包含重复的键;每个键最多只能映射到一个值。
元素类型没有限制,需要用户确保数据
key
的唯一性。
map
类型是对SQL标准的扩展。
SQL
MAP<kt, vt>
java/scala
DataTypes.MAP(kt,vt);
其中的
kt
和
vt
都是
DataType
类型。
桥接到JVM数据类型
Java 类型InputOutputOutput
java.util.Map<kt, vt>
XX默认
java.util.Map<kt, vt>
Xorg.apache.flink.table.data.MapDataXX内部数据类型
该类型可以使用
MAP<kt, vt>
声明,其中
kt
是key元素的数据类型,
vt
是value元素的数据类型。
3.6.3. MULTISET
multiset
(=bag)数据类型。与
map
不同,它允许集合中的每个元素存在多个实例。每个唯一的值(包括NULL)可以保存多个。
元素类型没有限制,需要用户确保唯一性。
SQL
MULTISET<t>
t MULTISET
java/scala
DataTypes.MULTISET(t);
桥接到JVM数据类型
Java 类型InputOutputOutput
java.util.Map<t, java.lang.Integer>
XX默认,给每个值分配其对应个数
java.util.Map<t, java.lang.Integer>
子类Xorg.apache.flink.table.data.MapDataXX内部数据类型
该类型可以使用
MULTISET<t>
声明,其中t是所包含元素的数据类型。
MULTISET
是接近SQL标准的同义词。例如,
INT MULTISET
等价于
MULTISET<INT>
。
3.6.4. ROW
字段序列的数据类型。
字段由字段名、字段类型和可选描述组成。表中数据最特殊的类型就是 row 类型,每列中 row 类型字段中的所有属性位置都和列中的位置一一对应。
与SQL标准相比,可选的字段描述简化了复杂结构的处理。
行类型类似于其他非标准兼容框架中的
STRUCT
类型。
SQL
ROW<n0 t0, n1 t1,...>ROW<n0 t0 'd0', n1 t1 'd1',...>ROW(n0 t0, n1 t1,...)ROW(n0 t0 'd0', n1 t1 'd1',...)
java/scala
DataTypes.ROW(DataTypes.FIELD(n0,t0),DataTypes.FIELD(n1,t1),...);DataTypes.ROW(DataTypes.FIELD(n0,t0,d0),DataTypes.FIELD(n1,t1,d1),...);
n0
为字段名称,
t0
为字段类型,
d0
为字段描述。
桥接到JVM数据类型
Java 类型InputOutputOutputorg.apache.flink.types.RowXX默认org.apache.flink.table.data.RowDataXX内部数据结构
可以使用
ROW<n0 t0 'd0', n1 t1 'd1',…>
声明该类型,其中
n
是字段的唯一名称,
t
是字段的逻辑类型,
d
是字段的描述。
ROW(…)
是接近SQL标准的同义词。例如,
ROW(myField INT, myOtherField BOOLEAN)
等价于
ROW<myField INT, myOtherField BOOLEAN>
。
3.7. 用户自定义数据类型
目前还不完全支持用户自定义的数据类型。它们目前(从Flink 1.11开始)只在参数和函数返回类型中作为未注册的结构类型。
结构化类型类似于面向对象编程语言中的对象。它包含零个、一个或多个属性。每个属性由名称和类型组成。
有两种结构化类型:
- 存储在
catalog
中并由catalog
标识符标识的类型(如cat.db.MyType)。这些等同于结构化类型的SQL标准定义。 - 匿名定义、未注册的类型(通常通过反射提取),由其实现类(如com.myorg.model.MyType)标识。这些类型在以编程方式定义表程序中很有用。它们允许重用现有的JVM类,而无需再次手动定义数据类型的模式。
注册的结构化类型
目前还不支持注册结构化类型。因此,它们不能存储在
catalog
中,也不能在
CREATE TABLE DDL
中引用。
未注册的结构化类型
可以使用自动反射提取从常规
pojo
(普通Java对象)创建未注册的结构化类型。
结构化类型的实现类必须满足以下要求:
- 类必须是全局可访问的,这意味着它必须声明为
public、static
,而不是abstract
。 - 类必须提供一个零参数的默认构造函数或一个赋值所有字段的完整参数的构造函数。
- 类的所有字段必须可以通过
public
声明或遵循公共编码风格的getter
(如getField(), isField(), field())方法读取。 - 类的所有字段必须由
public
声明、有完整参数的构造函数或遵循公共编码风格的setter
(如setField(…)、field(…))方法写入。 - 所有字段必须可以通过隐式地反射提取或使用
@DataTypeHint
注释显式地映射到数据类型。 - 声明为
static
或transient
的字段将被忽略。
反射提取支持字段的任意嵌套,只要字段类型不传递性地引用自身。
声明的字段类行(例如public int age)必须在受支持的JVM桥接类列表中,例如
in
t 为:
java.lang.Integer
或
int
。
对于某些类,需要一个注释来将类映射到具体的数据类型(例如
@DataTypeHint("DECIMAL(10,2)
")来为
java.math.BigDecimal
指定固定的精度和比例)。
JAVA
classUser{// 自动抽取数据类型publicint age;publicString name;//通过注解丰富其精度信息public@DataTypeHint("DECIMAL(10, 2)")BigDecimal totalBalance;//强制使用RAW类型丰富提取public@DataTypeHint("RAW")Class<?> modelClass;}DataTypes.of(User.class);
scala
caseclass User(// 自动抽取数据类型
age:Int,
name:String,//通过注解丰富其精度信息@DataTypeHint("DECIMAL(10, 2)") totalBalance: java.math.BigDecimal,//强制使用RAW类型丰富提取@DataTypeHint("RAW") modelClass: Class[_])
DataTypes.of(classOf[User])
桥接到JVM数据类型
Java 类型InputOutputOutputclassXX输入:该类或其子类。输出:子类。
默认org.apache.flink.types.RowXX代表row类型的结构体org.apache.flink.table.data.RowDataXX内部数据类型
3.8. 其他数据类型
3.8.1. BOOLEAN
布尔数据类型,值为:
TRUE
、
FALSE
或
UNKNOWN
。
SQL
BOOLEAN
java/scala
DataTypes.BOOLEAN();
桥接到JVM数据类型
Java 类型InputOutputOutputjava.lang.BooleanXX默认booleanX(X)类型为非空null时才会输出
3.8.2. RAW
任意序列化类型的数据类型。这种类型是表生态系统中的黑盒,仅在边缘处进行反序列化。
该类型是对SQL标准的扩展。
SQL
RAW('class','snapshot')
java/scala
DataTypes.RAW(class,serializer);DataTypes.RAW(class);
桥接到JVM数据类型
Java 类型InputOutputOutputclassXX默认。输入:原始类或子类。输出:子类byte[]Xorg.apache.flink.table.data.RawValueDataXX内部数据结构
SQL/Java/Scala
该类型可以使用
RAW('class', 'snapshot')
声明,其中
class
是原始类,
snapshot
是Base64编码的序列化的
TypeSerializerSnapshot
。
通常,类型字符串不是直接声明的,而是在持久化类型时生成的。
在API中,RAW类型可以通过直接提供
Class + TypeSerializer
或者通过传递Class并让框架从中提取
Class + TypeSerializer
来声明。
3.8.3. NULL
表示非类型NULL值的数据类型。
NULL
类型是对SQL标准的扩展。
NULL
类型除了
null
以外没有其他值,因此,它可以被强制转换为任何可为空的类型,类似于JVM语义。
这种类型有助于在API调用中表示未知类型,这些调用使用
NULL
字面量,并桥接到JSON或Avro等格式,这些格式也定义了这种类型。
这种类型在实践中不是很有用,这里只是为了完整性而提到它。
SQL
NULL
java/scala
DataTypes.NULL();
桥接到JVM数据类型
Java 类型InputOutputOutputjava.lang.ObjectXX默认任何类(X)任何非原始类型
4. 数据类型提取
在API中,Flink会尝试使用反射从类信息中自动提取数据类型,以避免重复的手动指定工作。但是,反射式提取数据类型并不总是成功的,因为可能缺少逻辑信息。
因此,可能需要在类或字段声明附近添加额外的信息,以支持提取逻辑。
下表列出了可以隐式映射到数据类型而不需要进一步添加额外信息的类。
如果你想使用
Scala
类,建议使用装箱类型(例如
java.lang.Integer
),而不是
Scala
的原生类。
Scala
的原生类(例如
Int
或
Doubl
e)被编译为JVM原生类(例如
Int
/
Double
),结果如下表所示,增加
NOT NULL
语义。
此外,
Scala
原生类的泛型(例如
java.util.Map[Int, Double]
)在编译过程中会被擦除,最后结果类似于:
java.util.Map[java.lang.Object, java.lang.Object]
。
Class数据类型java.lang.StringSTRINGjava.lang.BooleanBOOLEANbooleanBOOLEAN NOT NULLjava.lang.ByteTINYINTbyteTINYINT NOT NULLjava.lang.ShortSMALLINTshortSMALLINT NOT NULLjava.lang.IntegerINTintINT NOT NULLjava.lang.LongBIGINTlongBIGINT NOT NULLjava.lang.FloatFLOATjava.lang.FloatFLOATfloatFLOAT NOT NULLjava.lang.DoubleDOUBLEdoubleDOUBLE NOT NULLjava.sql.DateDATEjava.time.LocalDateDATEjava.sql.TimeTIME(0)java.time.LocalTimeTIME(9)java.sql.TimestampTIMESTAMP(9)java.time.LocalDateTimeTIMESTAMP(9)java.time.OffsetDateTimeTIMESTAMP(9) WITH TIME ZONEjava.time.InstantTIMESTAMP_LTZ(9)java.time.DurationINTERVAL SECOND(9)java.time.PeriodINTERVAL YEAR(4) TO MONTHbyte[]BYTEST[]
ARRAY<T>
java.util.Map<K, V>
MAP<K, V>
structured type T匿名 structured type T
本章节中提到的其他JVM桥接类需要
@DataTypeHint
注解。
数据类型提示可以参数化或替换单个函数参数和返回类型、结构化类或结构化类的字段的默认提取逻辑。开发者可以通过声明
@DataTypeHint
注解来选择应该在多大程度上修改默认提取逻辑。
@DataTypeHint
注解提供了一组可选的提示参数。下面的示例显示了其中一些参数。更多信息可以在注解类的文档中找到。
java
importorg.apache.flink.table.annotation.DataTypeHint;classUser{//将java.lang.Integer类转化为 INT 数据类型public@DataTypeHint("INT")Object o1;// 使用显式转换类定义毫秒精度的TIMESTAMP数据类型public@DataTypeHint(value ="TIMESTAMP(3)", bridgedTo =java.sql.Timestamp.class)Object o2;//强制使用RAW类型来丰富类型提取public@DataTypeHint("RAW")Class<?> modelClass;// 定义所有出现的java.math.BigDecimal(也包括嵌套字段)将被提取为DECIMAL(12, 2)public@DataTypeHint(defaultDecimalPrecision =12, defaultDecimalScale =2)AccountStatement stmt;// 定义每当类型不能映射到数据类型时,不要抛出异常,而应始终将其视为RAW类型public@DataTypeHint(allowRawGlobally =HintFlag.TRUE)ComplexModel model;}
scala
importorg.apache.flink.table.annotation.DataTypeHintclassUser{//将java.lang.Integer类转化为 INT 数据类型@DataTypeHint("INT")var o:AnyRef// 使用显式转换类定义毫秒精度的TIMESTAMP数据类型@DataTypeHint(value ="TIMESTAMP(3)", bridgedTo =java.sql.Timestamp.class)var o:AnyRef//强制使用RAW类型来丰富类型提取@DataTypeHint("RAW")var modelClass:Class[_]// 定义所有出现的java.math.BigDecimal(也包括嵌套字段)将被提取为DECIMAL(12, 2)@DataTypeHint(defaultDecimalPrecision =12, defaultDecimalScale =2)var stmt:AccountStatement// 定义每当类型不能映射到数据类型时,不要抛出异常,而应始终将其视为RAW类型@DataTypeHint(allowRawGlobally =HintFlag.TRUE)var model:ComplexModel}
版权归原作者 第一片心意 所有, 如有侵权,请联系我们删除。