0


flink-sql所有数据类型-1.15

1. 版本说明

本文档内容基于

flink-1.15.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

实例有两个职责:

  1. 声明一个逻辑类型:这并不是定义传输或存储的具体物理表示,但其定义了基于 jvm/Python 语言和表生态系统之间的边界。
  2. 可选:将数据的物理表示提示给 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注释显式地映射到数据类型。
  • 声明为statictransient的字段将被忽略。

反射提取支持字段的任意嵌套,只要字段类型不传递性地引用自身。

声明的字段类行(例如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. 数据类型转换CAST

Flink Table API

SQL

可以将定义的输入类型转化为目标类型,不管输入值是什么,有些转化操作都会成功,但是有些转化会在运行时失败,比如无法为目标类型创建一个正确的值。
举例:通常来说,可以将一个

INT

值转化为

STRING

,但是并不是什么时候都可以将

INT

值转化为

STRING

在计划期间,查询校验器在遇到校验异常时拒绝无效类型对的查询,比如尝试将

TIMESTAMP

转化为

INTERVAL

类型。查询校验器会接受可能在运行时失败的有效类型对,但是要求用户正确的处理运行失败。

Flink Table API

 SQL

中,转化可以使用以下两个内建函数之一来执行:

  • CAST:SQL 标准定义的常规转化函数,该函数会在转化不可靠或者是提供的输入无效时造成任务失败。类型推断将会保留输入类型的可空性(NULL)。
  • TRY_CAST:常规转换函数的扩展函数,在转换操作失败时返回 NULL 值,该函数的返回类型一直保持可空性(NULL)。

比如:

CAST('42'ASINT)--- 返回 INT NOT NULL 类型的 42
CAST(NULLASVARCHAR)--- 返回 VARCHAR 类型的 NULL
CAST('non-number'ASINT)--- 抛出异常,并且将任务运行失败

TRY_CAST('42'ASINT)--- 返回 INT 类型的 42
TRY_CAST(NULLASVARCHAR)--- 返回 VARCHAR 类型的 NULL
TRY_CAST('non-number'ASINT)--- 返回 INT 类型的 NULLCOALESCE(TRY_CAST('non-number'ASINT),0)--- 返回 INT NOT NULL 类型的 0

可空性解释:在

flink-1.15.x

版本之前,如果你在 SQL 中使用了

if

case when

表达式,在满足条件时,你想让结果为

NULL

,此时直接写

NULL

,是无法运行的。
但在

flink-1.15.x

中,可以使用新版的转化函数,将

NULL

值转化为对应字段的类型,以此来使用

NULL

下面的表格展示了支持的可转化类型对,“Y”表示支持,“!”表示失败,“N”表示还不支持。
Input\TargetCHAR¹/VARCHAR¹/STRINGBINARY¹/VARBINARY¹/BYTESBOOLEANDECIMALTINYINTSMALLINTINTEGERBIGINTFLOATDOUBLEDATETIMETIMESTAMPTIMESTAMP_LTZINTERVALARRAYMULTISETMAPROWSTRUCTUREDRAWCHAR/VARCHAR/STRINGY!!!!!!!!!!!!!NNNNNNNBINARY/VARBINARY/BYTESYYNNNNNNNNNNNNNNNNNNNBOOLEANYNYYYYYYYYNNNNNNNNNNNDECIMALYNNYYYYYYYNNNNNNNNNNNTINYINTYNYYYYYYYYNNN²N²NNNNNNNSMALLINTYNYYYYYYYYNNN²N²NNNNNNNINTEGERYNYYYYYYYYNNN²N²Y⁵NNNNNNBIGINTYNYYYYYYYYNNN²N²Y⁶NNNNNNFLOATYNNYYYYYYYNNNNNNNNNNNDOUBLEYNNYYYYYYYNNNNNNNNNNNDATEYNNNNNNNNNYNYYNNNNNNNTIMEYNNNNNNNNNNYYYNNNNNNNTIMESTAMPYNNNNNNNNNYYYYNNNNNNNTIMESTAMP_LTZYNNNNNNNNNYYYYNNNNNNNINTERVALYNNNNNY⁵Y⁶NNNNNNYNNNNNNARRAYYNNNNNNNNNNNNNN!³NNNNNMULTISETYNNNNNNNNNNNNNNN!³NNNNMAPYNNNNNNNNNNNNNNNN!³NNNROWYNNNNNNNNNNNNNNNNN!³NNSTRUCTUREDYNNNNNNNNNNNNNNNNNN!³NRAWY!NNNNNNNNNNNNNNNNNNY⁴
注(下面这些数字对应表中的右上角数字):

  1. 所有转化为固定或可变长度的类型,都会根据类型定义对结果值进行截取或使用空格填充。
  2. 必须使用 TO_TIMESTAMP 和 TO_TIMESTAMP_LTZ ,而不是 CAST/TRY_CAST。
  3. 如果子类型对支持,则支持,如果子类型对不支持,则失败。
  4. 如果 RAW 类和序列化类相等,则支持。
  5. 如果 INTERVAL 在 MONTH TO YEAR 范围内,则支持。
  6. 如果 INTERVAL 在 DAY TO TIME 范围内,则支持。

另外,不管是使用

CAST

还是

TRY_CAST

函数,转化

NULL

都只会返回

NULL

值。

4.1. 旧版转化

指1.15.x之前的版本。

可以设置

table.exec.legacy-cast-behaviour

enabled

来使用

 Flink-1.15

之前的转化操作,在

Flink-1.15

中,该设置默认禁用。

开启该参数,将会导致:

  1. 转化为 CHAR/VARCHAR/BINARY/VARBINARY 类型时,将不会对结果值进行截取或填充。
  2. CAST 永远不会失败,而是返回 NULL ,就像是 TRY_CAST 的行为,但是不会参考正确的类型。
  3. 转化一些值为 CHAR/VARCHAR/STRING 类型时,将会产生稍微不同的结果。

我们不推荐开启该参数,并且强烈建议新的项目保持禁用该参数,并且使用新的转化行为。该参数将会在下个 flink 版本中移除。

5. 数据类型提取

在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}

本文转载自: https://blog.csdn.net/u012443641/article/details/127706734
版权归原作者 第一片心意 所有, 如有侵权,请联系我们删除。

“flink-sql所有数据类型-1.15”的评论:

还没有评论