首页 / 工具 / 迁移清单 / Hologres → Flink SQL
Hologres 迁移到 Flink SQL 的函数改写清单
从 Hologres 迁移到 Flink SQL 时,在 Hologres 有对应写法的 43 个常用函数中,26 个需要改写(其中 1 个在 Flink SQL 没有对应函数),另有 4 个可以改用 Flink SQL 的原生函数。逐个列出两边写法和注意事项。
需要改写的函数 · 可以改用原生函数 · 迁移注意事项 · 可以直接用的函数 · 反向:Flink SQL 迁移到 Hologres
需要改写的函数
| 函数 | Hologres 写法 | Flink SQL 写法 | Flink SQL 说明 |
|---|---|---|---|
| ADD_MONTHS | d + interval '1 month' | 需改写 TIMESTAMPADD(MONTH, n, timepoint) | 内置函数中没有 ADD_MONTHS,用 TIMESTAMPADD 的 MONTH 单位。 |
| ANY_VALUE | MAX(col) | 需改写 FIRST_VALUE(expression) | 内置函数中没有 ANY_VALUE,可以用聚合函数 FIRST_VALUE 代替。 |
| APPROX_COUNT_DISTINCT | APPROX_COUNT_DISTINCT(column) | 需改写 COUNT(DISTINCT expr) | 内置函数文档中没有近似去重函数,只能用精确的 COUNT(DISTINCT)。 |
| DATE_ADD | DATEADD(d, num, 'day') | 需改写 TIMESTAMPADD(DAY, n, timepoint) | 内置函数中没有 DATE_ADD,改用 TIMESTAMPADD。 |
| DATE_FORMAT | TO_CHAR(timestamp, 'YYYY-MM-DD HH24:MI:SS') | 支持 DATE_FORMAT(timestamp, format) | 按格式字符串把 TIMESTAMP 转换为字符串。 |
| DATE_SUB | d - interval '1 day' | 需改写 TIMESTAMPADD(DAY, -n, timepoint) | 内置函数中没有 DATE_SUB,用 TIMESTAMPADD 传负数。 |
| DATEADD | DATEADD(d, num, str) | 需改写 TIMESTAMPADD(unit, n, timepoint) | 单位可以是 SECOND、MINUTE、HOUR、DAY、WEEK、MONTH、QUARTER 或 YEAR。 |
| DATEDIFF | DATEDIFF(d1, d2, unit) | 需改写 TIMESTAMPDIFF(DAY, timepoint1, timepoint2) | 内置函数中没有 DATEDIFF。TIMESTAMPDIFF 返回 timepoint1 与 timepoint2 之间带符号的单位数,先写单位,再写开始时间和结束时间。 |
| DATETRUNC | DATE_TRUNC('month', ts) | 需改写 FLOOR(timepoint TO MONTH) | 内置函数中没有 DATE_TRUNC,用 FLOOR ... TO 向下取整到指定单位。 |
| FROM_JSON | json_str::jsonb ->> 'key' | 需改写 JSON_VALUE(json, path) / JSON_QUERY(json, path) | 没有 FROM_JSON。JSON_VALUE 取标量值,JSON_QUERY 取对象或数组,返回 JSON 字符串。 |
| FROM_UNIXTIME | TO_TIMESTAMP(seconds) | 支持 FROM_UNIXTIME(numeric[, string]) | 返回字符串,默认格式 yyyy-MM-dd HH:mm:ss,结果按会话时区表示。 |
| GET_JSON_OBJECT | GET_JSON_OBJECT(json, json_path) | 需改写 JSON_VALUE(json, path) | 提取 JSON 中的标量值,可以用 RETURNING 子句指定返回类型。 |
| INSTR | STRPOS(str, substr) | 支持 INSTR(string1, string2) | 任一参数为 NULL 时返回 NULL。需要起始位置时用 LOCATE(string1, string2, integer),找不到时返回 0。 |
| LAST_DAY | LAST_DAY(ts) | 需改写 TIMESTAMPADD(DAY, -1, TIMESTAMPADD(MONTH, 1, FLOOR(ts TO MONTH))) | 内置函数中没有 LAST_DAY。先用 FLOOR 取当月第一天,加一个月再减一天。 |
| LENGTH | LENGTH(str) | 别名 CHAR_LENGTH(string) | 返回字符数,别名 CHARACTER_LENGTH。内置函数中没有 LENGTH。 |
| MAX_BY | MAX_BY(x, y) | 需改写 ROW_NUMBER() OVER (PARTITION BY ... ORDER BY y DESC) = 1 | 内置函数中没有 MAX_BY 或 ARG_MAX,用 ROW_NUMBER 窗口函数改写。 |
| MAX_PT | MAX_PT('table_name') | 不支持 | 内置函数中没有 MAX_PT。流式作业没有“最新分区”的概念,批模式下可以用子查询改写。 |
| MONTHS_BETWEEN | (EXTRACT(YEAR FROM a) - EXTRACT(YEAR FROM b)) * 12 + EXTRACT(MONTH FROM a) - EXTRACT(MONTH FROM b) | 需改写 TIMESTAMPDIFF(MONTH, start, end) | 没有 MONTHS_BETWEEN。TIMESTAMPDIFF 返回 timepoint2 减 timepoint1 的整数,参数顺序与 MONTHS_BETWEEN 相反。 |
| NVL | COALESCE(value, default_value) | 需改写 IFNULL(input, null_replacement) | 没有 NVL,可以用 IFNULL 或 COALESCE。 |
| PERCENTILE_APPROX | APPROX_PERCENTILE(p) WITHIN GROUP (ORDER BY col) | 需改写 PERCENTILE(expr, percentage[, frequency]) | PERCENTILE 是精确分位数,按线性插值计算。2.0 起的文档中有这个函数,1.20 的文档中没有,使用前请按所用版本确认。文档提示在普通分组聚合中开销较大,建议用在窗口场景。 |
| REGEXP_EXTRACT | (REGEXP_MATCH(str, pattern))[n] | 支持 REGEXP_EXTRACT(string1, string2[, integer]) | 分组下标从 1 开始,0 表示整个匹配,下标不能超过定义的分组数。 |
| SIZE | ARRAY_LENGTH(arr, 1) | 别名 CARDINALITY(array_or_map) | 数组返回元素个数,Map 返回键值对个数。 |
| SPLIT | REGEXP_SPLIT_TO_ARRAY(str, pattern) | 支持 SPLIT(string, delimiter) | 字符串或分隔符为 NULL 时返回 NULL。只取第 n 段可以用 SPLIT_INDEX。 |
| SPLIT_PART | SPLIT_PART(str, delimiter, num) | 需改写 SPLIT_INDEX(str, delimiter, n - 1) | 下标从 0 开始。下标为负数或任一参数为 NULL 时返回 NULL。 |
| TO_CHAR | TO_CHAR(ts, 'YYYY-MM-DD HH24:MI:SS') | 需改写 DATE_FORMAT(timestamp, 'yyyy-MM-dd HH:mm:ss') | 没有 TO_CHAR。DATE_FORMAT 的格式符兼容 Java SimpleDateFormat。 |
| WM_CONCAT | STRING_AGG(expression, delimiter) | 需改写 LISTAGG(expression[, separator]) | 分隔符写在后面。 |
可以改用原生函数
下面的函数在 Hologres 中只能用替代写法,Flink SQL 有对应的函数。原来的写法通常仍能运行,换成原生函数会更简洁。
| 函数 | Hologres 写法 | Flink SQL 写法 | Flink SQL 说明 |
|---|---|---|---|
| DAYOFWEEK | EXTRACT(DOW FROM ts) + 1 | 支持 DAYOFWEEK(date) | 返回 1~7,等价于 EXTRACT(DOW FROM date)。文档示例中 1994-09-27(周二)返回 3,即周日为 1。 |
| SUBSTR | SUBSTRING(str FROM start FOR len) | 支持 SUBSTR(string, integer1[, integer2]) | 也可以写 SUBSTRING。省略长度时截取到末尾。 |
| UNIX_TIMESTAMP | EXTRACT(EPOCH FROM ts) | 支持 UNIX_TIMESTAMP(string1[, string2]) | 默认格式 yyyy-MM-dd HH:mm:ss。不带参数时返回当前时间的秒数。 |
| WEEKOFYEAR | EXTRACT(WEEK FROM ts) | 别名 WEEK(date) | 返回 1~53,等价于 EXTRACT(WEEK FROM date)。 |
迁移注意事项
ADD_MONTHS 按月加减
- Hologres 和 Flink 的月末行为文档没有写明,迁移涉及月末日期时建议用已知数据核对。
APPROX_COUNT_DISTINCT 近似去重计数
- 各引擎的误差不同:MaxCompute 文档写的是 5%,Hologres 默认是 0.1%~1%。迁移后与原报表对数时,小的差异属于正常现象,不能直接当作数据问题。
- 改写成 Hive 或 Flink 的 COUNT(DISTINCT) 后结果是精确值,但资源消耗会明显变大,大数据量下要评估内存和运行时间。
- Spark 的第二个参数 relativeSD 在其他引擎中没有对应写法,迁移时要去掉,并按目标引擎的方式调整精度,例如 Hologres 的会话参数。
DATE_FORMAT 日期格式化
- 从 MaxCompute 默认模式迁出时,hh:mi:ss 要改成目标引擎的分钟写法。原样照搬到 Spark 或 Flink,mi 不会被识别为分钟。
- Hologres 的 HH 默认是 12 小时制,下午的时间会少 12 小时,必须写 HH24。
DATEADD 按单位加减日期
- MaxCompute 和 Hologres 中 mm 表示月,mi 表示分钟。把 DATEADD(d, 1, 'mm') 当成加 1 分钟,是迁移时最常见的错误。
- Hologres 的 DATEADD 默认只支持 1925~2282 年。9999-12-31 这类表示“永久有效”的日期需要单独处理。
DATEDIFF 日期差
- MaxCompute、StarRocks、Doris、Hive 和 Spark 都是结束日期在前。Flink 的 TIMESTAMPDIFF 先写单位,再写开始时间和结束时间。Flink 文档没有写明正负号的方向,按标准 SQL 的约定结果为 timepoint2 减 timepoint1,迁移后建议用一条已知数据核对符号。
- Hologres 的 DATEDIFF 有版本要求,V2.1.0~V2.1.12 之间的版本不支持。
DATETRUNC 日期截断
- 参数顺序不同:MaxCompute 是日期在前,Hologres、StarRocks 和 Spark 是单位在前,Doris 两种都接受。
- 返回类型不同:MaxCompute 对 DATE 输入返回 DATE,Hologres 和 Spark 的 date_trunc 返回时间戳。结果用于关联 DATE 字段时要先转换。
FROM_UNIXTIME 时间戳转日期
- 返回类型不同:MaxCompute 返回 DATETIME,Hologres 的 TO_TIMESTAMP 返回 TIMESTAMPTZ,其他引擎返回字符串。拿结果做日期计算前,确认是否需要再转换类型。
GET_JSON_OBJECT 提取 JSON 字段
- Hologres 报错 function get_json_object (text, unknown) does not exist 时,常见原因有两个:RAM 用户没有扩展所在 schema 的查询权限,或者第一个参数不是 TEXT 类型。前者可以把扩展建在 pg_catalog 下,后者需要先 CAST 为 text。
INSTR 查找子串位置
- MaxCompute 的三参数和四参数写法,例如 INSTR(s, 'e', 3, 2),在 StarRocks、Doris、Hive、Spark 和 Flink 中都没有对应写法。只传起始位置时可以改成 LOCATE,取第 N 次出现时需要改写成多步计算。
- Hologres 的 INSTR 依赖 orafce 扩展。没有安装扩展时 SQL 会报函数不存在,改用 STRPOS 即可。
LAST_DAY 当月最后一天
- Hologres 的 LAST_DAY 有版本要求,V2.1.0~V2.1.12 之间的版本不支持。
LENGTH 字符串长度
- 按字符计数统一写 CHAR_LENGTH 最稳妥:Hologres、StarRocks、Doris、Flink 都支持,Hive 2.2.0 起也支持(char_length 是 character_length 的简写)。
MONTHS_BETWEEN 相差月数
- Flink 的 TIMESTAMPDIFF(MONTH, t1, t2) 计算的是 t2 减 t1,开始时间在前;MONTHS_BETWEEN 是结束时间在前。照搬参数顺序会得到相反的符号。
- StarRocks 的 months_diff、Flink 的 TIMESTAMPDIFF 和 Hologres 的 EXTRACT 写法都只返回整数月,原 SQL 中依赖小数部分的计算(例如按 0.5 个月判断)需要重新设计。
NVL 空值替换
- 迁移到 Hologres、StarRocks 或 Flink SQL 时,统一改写为 COALESCE 最省事,因为 COALESCE 在七个引擎中都可用。
- Flink 的 IFNULL 在第一个参数来自 JSON_VALUE 时可能返回错误结果,问题编号 FLINK-35832。受影响版本包括 1.15~1.20 和 2.0.0,问题已在 2024 年 7 月标记为修复,但没有写明修复版本,使用前请确认所用版本是否包含修复。
PERCENTILE_APPROX 近似分位数
- 各引擎的算法不同,结果不会完全一致。MaxCompute 文档写明 p 落在两个值中间时取两者均值,Spark 返回满足条件的最小值,Flink 的 PERCENTILE 用线性插值。P50、P99 这类指标迁移后要实测对比。
- Hologres 的 APPROX_PERCENTILE 需要 V3.1 及以上版本,而且只抽样 8,192 个元素。数据量很大时,尾部分位数(例如 P999)的误差可能偏大。
- Flink 的 PERCENTILE 是精确计算,每条记录都可能触发全量排序。文档建议用在窗口聚合中,流式分组聚合中慎用。
REGEXP_EXTRACT 正则提取
- 第三个参数是否必填不一样:MaxCompute、Spark 和 Flink 可以省略,默认取第 1 组;StarRocks、Doris 和 Hive 必须写上。迁移时统一写出分组下标最稳妥。
SIZE 数组和 Map 元素个数
- Hologres 文档中 ARRAY_LENGTH 的签名带维度参数,一维数组也要写成 ARRAY_LENGTH(arr, 1)。
SPLIT 字符串拆分
- 只需要取某一段时,Hologres 的 SPLIT_PART 和 Flink 的 SPLIT_INDEX 更直接。注意 SPLIT_PART 的序号从 1 开始,SPLIT_INDEX 为负数时返回 NULL。
SPLIT_PART 按分隔符取第 N 段
- 下标越界时结果不同:MaxCompute、StarRocks 和 Spark 返回空字符串,Hologres 和 Doris 返回 NULL。下游用 IS NULL 或 = '' 判断时,迁移后结果可能变化。
- Hive 的数组下标和 Flink 的 SPLIT_INDEX 都从 0 开始。从 SPLIT_PART 改写时要把下标减 1。
TO_CHAR 日期转字符串
- MaxCompute 的 'yyyy-mm-dd' 原样搬到 Hive、Spark 或 Flink,mm 会被当成分钟,结果类似 2026-30-14,而且不会报错。Java 风格要写 'yyyy-MM-dd'。
- Hologres 的 HH 默认是 12 小时制,下午 3 点会输出 03。需要 24 小时制时写 HH24。
DAYOFWEEK 星期几
- Hologres 的 EXTRACT(DOW ...) 以周日为 0,直接替换 DAYOFWEEK 会让每天都差 1,周日从 1 变成 0。
- “星期几”的编号有三种:DAYOFWEEK 周日为 1;MaxCompute 和 Spark 的 WEEKDAY 周一为 0;Hologres 的 ISODOW 周一为 1、周日为 7。迁移时先确认原 SQL 用的是哪一种。
- 需要“周一为 1、周日为 7”时,可以写成 (DAYOFWEEK(d) + 5) % 7 + 1,在 Hologres 中直接用 EXTRACT(ISODOW FROM d)。
SUBSTR 截取子串
- Hologres 直接写 SUBSTR 可能报函数不存在,需要先创建 orafce 扩展,或改用标准的 SUBSTRING。
UNIX_TIMESTAMP 日期转时间戳
- 格式参数的写法不同:StarRocks 和 Doris 用 %Y-%m-%d %H:%i:%s,Hive、Spark 和 Flink 用 yyyy-MM-dd HH:mm:ss,MaxCompute 不支持格式参数。
WEEKOFYEAR 一年中的第几周
- Hologres 的 EXTRACT 返回 DOUBLE PRECISION,直接拼接字符串会得到 12.0 这类结果,需要先 CAST 成整数。
可以直接用的函数
下面 13 个函数在两个引擎中写法相同。参数、返回值和边界情况仍可能不同,点开函数页查看细节。