(二十一)Flink Table API & SQL 编程指南 Data Types

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 TypeRemarks 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]。

ClassData Type
java.lang.StringSTRING
java.lang.BooleanBOOLEAN
booleanBOOLEAN NOT NULL
java.lang.ByteTINYINT
byteTINYINT NOT NULL
java.lang.ShortSMALLINT
shortSMALLINT NOT NULL
java.lang.IntegerINT
intINT NOT NULL
java.lang.LongBIGINT
longBIGINT NOT NULL
java.lang.FloatFLOAT
floatFLOAT NOT NULL
java.lang.DoubleDOUBLE
doubleDOUBLE NOT NULL
java.sql.DateDATE
java.time.LocalDateDATE
java.sql.TimeTIME(0)
java.time.LocalTimeTIME(9)
java.sql.TimestampTIMESTAMP(9)
java.time.LocalDateTimeTIMESTAMP(9)
java.time.OffsetDateTimeTIMESTAMP(9) WITH TIME ZONE
java.time.InstantTIMESTAMP_LTZ(9)
java.time.DurationINTERVAL SECOND(9)
java.time.PeriodINTERVAL YEAR(4) TO MONTH
byte[]BYTES
T[]ARRAY
java.util.Map<K, V>MAP<K, V>
structured type Tanonymous structured type T

本文档中提到的其他 JVM 桥接类需要@DataTypeHint注释。

数据类型提示可以参数化或替换单个函数参数和返回类型、结构化类或结构化类字段的默认提取逻辑。实现者可以通过声明@DataTypeHint注释来选择应在多大程度上修改默认提取逻辑。

@DataTypeHint注释提供一组可选的提示参数。以下示例中显示了其中一些参数。有关详细信息,请参阅注释类的文档。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,以下是一个基于Flink1.14.3 Table SQL API的MySQL列加工数据处理JAVA代码的示例: ```java import org.apache.flink.api.common.typeinfo.TypeInformation; import org.apache.flink.api.java.ExecutionEnvironment; import org.apache.flink.api.java.typeutils.RowTypeInfo; import org.apache.flink.connector.jdbc.JdbcInputFormat; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.table.api.EnvironmentSettings; import org.apache.flink.table.api.Table; import org.apache.flink.table.api.TableEnvironment; import org.apache.flink.table.api.bridge.java.StreamTableEnvironment; import org.apache.flink.types.Row; public class MySQLColumnProcessing { public static void main(String[] args) throws Exception { // 创建执行环境 StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); StreamTableEnvironment tEnv = StreamTableEnvironment.create(env, EnvironmentSettings.newInstance().useBlinkPlanner().inStreamingMode().build()); // 定义MySQL连接信息 String url = "jdbc:mysql://localhost:3306/test"; String username = "root"; String password = "root"; String driverName = "com.mysql.jdbc.Driver"; // 定义MySQL输入格式 JdbcInputFormat jdbcInputFormat = JdbcInputFormat.buildJdbcInputFormat() .setDrivername(driverName) .setDBUrl(url) .setUsername(username) .setPassword(password) .setQuery("SELECT * FROM user") .setRowTypeInfo(new RowTypeInfo(TypeInformation.of(Integer.class), TypeInformation.of(String.class), TypeInformation.of(Integer.class))) .finish(); // 创建一个表,并将MySQL数据源注册为表 Table table = tEnv.fromDataStream(env.createInput(jdbcInputFormat), "id, name, age"); tEnv.registerTable("user", table); // 使用SQL API进行列加工处理 Table result = tEnv.sqlQuery("SELECT id, CONCAT('My name is ', name) as name, age+1 as age FROM user"); // 打印结果 tEnv.toRetractStream(result, Row.class).print(); // 执行任务 env.execute("MySQL Column Processing"); } } ``` 这个示例代码读取MySQL数据库中的`user`表数据,对`name`列进行字符串拼接,并对`age`列进行加1操作,最后将结果打印出来。您需要将MySQL连接信息替换为自己的连接信息,并根据具体的业务需求修改SQL查询语句。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

京河小蚁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值