首页 / 工具 / 迁移清单 / Hologres → StarRocks
Hologres 迁移到 StarRocks 的函数改写清单
从 Hologres 迁移到 StarRocks 时,在 Hologres 有对应写法的 43 个常用函数中,18 个需要改写(其中 1 个在 StarRocks 没有对应函数),另有 5 个可以改用 StarRocks 的原生函数。逐个列出两边写法和注意事项。
需要改写的函数 · 可以改用原生函数 · 迁移注意事项 · 可以直接用的函数 · 反向:StarRocks 迁移到 Hologres
需要改写的函数
| 函数 | Hologres 写法 | StarRocks 写法 | StarRocks 说明 |
|---|---|---|---|
| ADD_MONTHS | d + interval '1 month' | 支持 add_months(date, months) | 返回 DATETIME,DATE 输入也会转成 DATETIME。目标月份没有对应日期时返回当月最后一天,例如 2022-01-31 加 1 个月得到 2022-02-28。 |
| DATE_ADD | DATEADD(d, num, 'day') | 支持 DATE_ADD(date, INTERVAL n DAY) | 文档只列出 INTERVAL 写法。返回 DATETIME,DATE 输入也会转成 DATETIME。结果日期不存在时返回 NULL。 |
| DATE_FORMAT | TO_CHAR(timestamp, 'YYYY-MM-DD HH24:MI:SS') | 支持 DATE_FORMAT(datetime, '%Y-%m-%d %H:%i:%s') | MySQL 风格格式符,%m 是月,%i 是分钟。需要 yyyy-MM-dd 这类 Joda 风格时用 jodatime_format。结果超过 128 字节时返回 NULL。 |
| DATE_SUB | d - interval '1 day' | 支持 DATE_SUB(date, INTERVAL n DAY) | 别名 subdate。返回 DATETIME。结果日期不存在时返回 NULL,例如 2010-02-30。只传天数时可以用 days_sub(d, n)。 |
| DATEADD | DATEADD(d, num, str) | 需改写 TIMESTAMPADD(unit, n, datetime_expr) | 单位写成关键字,例如 HOUR、DAY、MONTH,不加引号。TIMESTAMPADD 文档没有列出 QUARTER;按季度加减可以用 DATE_ADD(dt, INTERVAL n QUARTER)。 |
| FROM_JSON | json_str::jsonb ->> 'key' | 需改写 parse_json(str) | 没有 FROM_JSON。parse_json 返回 JSON 类型,而不是 STRUCT 或 MAP。字符串不是合法 JSON 时返回 NULL。取字段可以接 json_query 或 -> 运算符。 |
| FROM_UNIXTIME | TO_TIMESTAMP(seconds) | 支持 from_unixtime(unix_timestamp[, string_format]) | 返回 VARCHAR,默认格式 yyyy-MM-dd HH:mm:ss。小于 0 或大于 253402243199 时返回 NULL。 |
| INSTR | STRPOS(str, substr) | 支持 instr(str, substr) | 按字符计数,下标从 1 开始,找不到时返回 0。需要指定起始位置时用 locate(substr, str, pos)。 |
| LENGTH | LENGTH(str) | 需改写 char_length(str) | LENGTH 返回的是字节数。按字符计数要用 char_length,别名 character_length,目前只支持 UTF-8。 |
| MAX_PT | MAX_PT('table_name') | 不支持 | 在 StarRocks 官方文档中搜索不到 MAX_PT。改写为 WHERE pt = (SELECT MAX(pt) FROM t)。 |
| MONTHS_BETWEEN | (EXTRACT(YEAR FROM a) - EXTRACT(YEAR FROM b)) * 12 + EXTRACT(MONTH FROM a) - EXTRACT(MONTH FROM b) | 需改写 months_diff(expr1, expr2) | 函数列表中没有 MONTHS_BETWEEN。months_diff 返回 expr1 减 expr2 的月数,类型是 BIGINT,只精确到月;日期不存在时返回 NULL。 |
| NVL | COALESCE(value, default_value) | 需改写 IFNULL(expr1, expr2) | 条件函数列表中没有 NVL,只有 case、coalesce、if、ifnull 和 nullif。IFNULL 的结果类型与 expr1 一致。 |
| PERCENTILE_APPROX | APPROX_PERCENTILE(p) WITHIN GROUP (ORDER BY col) | 支持 PERCENTILE_APPROX(expr, p[, compression]) | p 可以是单个值或数组。compression 取 2048~10000,不传或超出范围时按 10000 计算,值越大越精确,内存占用也越多。 |
| REGEXP_EXTRACT | (REGEXP_MATCH(str, pattern))[n] | 支持 regexp_extract(str, pattern, pos) | pos 是必填参数。没有匹配时返回空字符串。 |
| SPLIT | REGEXP_SPLIT_TO_ARRAY(str, pattern) | 支持 split(content, delimiter) | 返回 ARRAY<VARCHAR>。分隔符为空字符串时按单个字符拆分。文档没有说明分隔符是否按正则处理。 |
| TO_CHAR | TO_CHAR(ts, 'YYYY-MM-DD HH24:MI:SS') | 需改写 DATE_FORMAT(date, '%Y-%m-%d %H:%i:%s') | 没有 TO_CHAR。DATE_FORMAT 使用 MySQL 风格格式符,%i 表示分钟。结果超过 128 字节时返回 NULL。 |
| TO_DATE | TO_DATE(text, format) | 需改写 str_to_date(str, format) | StarRocks 的 to_date 只接受 DATETIME 并取日期部分,不能解析字符串。按格式解析用 str_to_date,格式符与 date_format 相同;格式只含日期时返回 DATE,否则返回 DATETIME。 |
| WM_CONCAT | STRING_AGG(expression, delimiter) | 需改写 GROUP_CONCAT([DISTINCT] expr [ORDER BY ...] [SEPARATOR sep]) | 默认分隔符是逗号,跳过 NULL。结果长度受 group_concat_max_len 限制,默认 1,024 个字符,超出部分会被截断。 |
可以改用原生函数
下面的函数在 Hologres 中只能用替代写法,StarRocks 有对应的函数。原来的写法通常仍能运行,换成原生函数会更简洁。
| 函数 | Hologres 写法 | StarRocks 写法 | StarRocks 说明 |
|---|---|---|---|
| ANY_VALUE | MAX(col) | 支持 ANY_VALUE(expr) | 返回值不确定。3.2 起支持 ARRAY、MAP 和 STRUCT 类型。 |
| DAYOFWEEK | EXTRACT(DOW FROM ts) + 1 | 支持 dayofweek(date) | 周日为 1,周一为 2,周六为 7。 |
| SUBSTR | SUBSTRING(str FROM start FOR len) | 支持 substr(str, pos[, len]) | substr 和 substring 是同一个函数。从 1 开始计数,负数从末尾倒数,pos 为 0 或超出长度时返回空字符串。 |
| UNIX_TIMESTAMP | EXTRACT(EPOCH FROM ts) | 支持 UNIX_TIMESTAMP([date[, fmt]]) | 返回 BIGINT。fmt 用 %Y-%m-%d 风格。早于 1970-01-01 或晚于 2038-01-19 11:14:07 时返回 0,结果受时区影响。 |
| WEEKOFYEAR | EXTRACT(WEEK FROM ts) | 支持 WEEKOFYEAR(date) | 返回 INT。文档没有说明周的划分规则;需要 ISO 周时可以用 week_iso。 |
迁移注意事项
ADD_MONTHS 按月加减
- 月末日期:StarRocks、Doris 和 Spark 在目标月份没有对应日期时取当月最后一天。StarRocks 文档特别说明,2022-02-28 加 1 个月得到 3 月 28 日而不是 3 月 31 日,这和 Oracle 的行为不同。
- Hologres 和 Flink 的月末行为文档没有写明,迁移涉及月末日期时建议用已知数据核对。
DATE_ADD 日期加减
- MaxCompute 的 DATEADD 按月加时,目标月份没有对应日期会返回当月最后一天,例如 1 月 29 日加 1 个月得到 2 月 28 日。StarRocks 的 DATE_ADD 遇到不存在的日期返回 NULL。
- StarRocks 的 DATE_ADD 即使输入是 DATE,也会返回 DATETIME。写入 DATE 列或与 DATE 比较时注意类型。
DATE_FORMAT 日期格式化
- Hologres 的 HH 默认是 12 小时制,下午的时间会少 12 小时,必须写 HH24。
- StarRocks 和 Doris 中 %m 是月、%i 是分钟,写成 %M 会输出英文月份名。
DATE_SUB 日期减天数
- StarRocks 的 DATE_SUB 即使输入是 DATE,也返回 DATETIME。结果用于分区过滤或与 DATE 字段比较时,注意类型是否一致。
- StarRocks 和 Doris 的 DATE_SUB 文档只列出 INTERVAL 写法。把 Hive 的 date_sub(d, 1) 搬到 StarRocks 时,改成 DATE_SUB(d, INTERVAL 1 DAY) 或 days_sub(d, 1)。
DATEADD 按单位加减日期
- MaxCompute 和 Hologres 中 mm 表示月,mi 表示分钟。把 DATEADD(d, 1, 'mm') 当成加 1 分钟,是迁移时最常见的错误。
- MaxCompute 按月加减时,如果目标月份没有对应日期,结果取当月最后一天。StarRocks 的 DATE_ADD 遇到不存在的日期返回 NULL。
- Hologres 的 DATEADD 默认只支持 1925~2282 年。9999-12-31 这类表示“永久有效”的日期需要单独处理。
FROM_JSON 按 schema 解析 JSON
- StarRocks 的 parse_json 和 Doris 的 JSON_PARSE 返回的是 JSON 类型,下游需要 STRUCT 或 MAP 时要再做一次转换,不能直接替换 from_json。
- 非法 JSON 的处理不同:StarRocks 的 parse_json 返回 NULL,Doris 的 JSON_PARSE 直接报错。脏数据较多的表,在 Doris 中改用 JSON_PARSE_ERROR_TO_NULL。
FROM_UNIXTIME 时间戳转日期
- 返回类型不同:MaxCompute 返回 DATETIME,Hologres 的 TO_TIMESTAMP 返回 TIMESTAMPTZ,其他引擎返回字符串。拿结果做日期计算前,确认是否需要再转换类型。
- StarRocks 和 Doris 对负数时间戳返回 NULL,1970 年以前的时间无法用这个函数转换。
INSTR 查找子串位置
- MaxCompute 的三参数和四参数写法,例如 INSTR(s, 'e', 3, 2),在 StarRocks、Doris、Hive、Spark 和 Flink 中都没有对应写法。只传起始位置时可以改成 LOCATE,取第 N 次出现时需要改写成多步计算。
- Hologres 的 INSTR 依赖 orafce 扩展。没有安装扩展时 SQL 会报函数不存在,改用 STRPOS 即可。
LENGTH 字符串长度
- StarRocks 和 Doris 的 LENGTH 返回字节数。像 WHERE LENGTH(name) > 10 这样的条件,迁移后对中文内容会多筛出很多行,而且不会报错。
- 按字符计数统一写 CHAR_LENGTH 最稳妥:Hologres、StarRocks、Doris、Flink 都支持,Hive 2.2.0 起也支持(char_length 是 character_length 的简写)。
MONTHS_BETWEEN 相差月数
- StarRocks 的 months_diff、Flink 的 TIMESTAMPDIFF 和 Hologres 的 EXTRACT 写法都只返回整数月,原 SQL 中依赖小数部分的计算(例如按 0.5 个月判断)需要重新设计。
NVL 空值替换
- 迁移到 Hologres、StarRocks 或 Flink SQL 时,统一改写为 COALESCE 最省事,因为 COALESCE 在七个引擎中都可用。
PERCENTILE_APPROX 近似分位数
- 第三个参数含义不同:MaxCompute 和 Hive 的 B、Spark 的 accuracy 都默认 10000;StarRocks 和 Doris 的 compression 只接受 2048~10000。从 Spark 迁移时,如果写了大于 10000 的 accuracy,要调整到这个范围内。
- Hologres 的 APPROX_PERCENTILE 需要 V3.1 及以上版本,而且只抽样 8,192 个元素。数据量很大时,尾部分位数(例如 P999)的误差可能偏大。
REGEXP_EXTRACT 正则提取
- 第三个参数是否必填不一样:MaxCompute、Spark 和 Flink 可以省略,默认取第 1 组;StarRocks、Doris 和 Hive 必须写上。迁移时统一写出分组下标最稳妥。
- 没有匹配时的返回值不同:StarRocks 和 Doris 文档写明返回空字符串,MaxCompute 只写明参数为 NULL 时返回 NULL。下游用 IS NULL 判断的逻辑迁移后要实测。
SPLIT 字符串拆分
- 只需要取某一段时,Hologres 的 SPLIT_PART 和 Flink 的 SPLIT_INDEX 更直接。注意 SPLIT_PART 的序号从 1 开始,SPLIT_INDEX 为负数时返回 NULL。
TO_CHAR 日期转字符串
- Hologres 的 HH 默认是 12 小时制,下午 3 点会输出 03。需要 24 小时制时写 HH24。
- StarRocks 和 Doris 的分钟是 %i,不是 %M。%M 表示英文月份名。
TO_DATE 字符串转日期
- 同名不同义:把 MaxCompute 的 TO_DATE('20261013', 'yyyymmdd') 直接搬到 StarRocks、Doris 或 Hive 会报错或得到错误结果,需要改用 str_to_date 或 unix_timestamp。
WM_CONCAT 分组拼接字符串
- StarRocks 的 GROUP_CONCAT 默认最多 1,024 个字符,超出部分不报错直接截断。长列表需要先调大 group_concat_max_len。
- 不写排序时,各引擎拼接的顺序都不固定。需要稳定结果时,MaxCompute 写 WITHIN GROUP (ORDER BY ...),StarRocks 和 Doris 在 GROUP_CONCAT 内写 ORDER BY。
- StarRocks 3.0.6 和 3.1.3 起,GROUP_CONCAT 必须用 SEPARATOR 关键字声明分隔符。
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 截取子串
- 起始位置写 0 是常见错误。MaxCompute 默认、StarRocks 和 Doris 都返回空字符串,不会报错,结果却全是空值,很难发现。MaxCompute 开启 Hive 兼容模式后又会按 1 处理,同一条 SQL 在不同模式下结果不同。
- Hologres 直接写 SUBSTR 可能报函数不存在,需要先创建 orafce 扩展,或改用标准的 SUBSTRING。
UNIX_TIMESTAMP 日期转时间戳
- 格式参数的写法不同:StarRocks 和 Doris 用 %Y-%m-%d %H:%i:%s,Hive、Spark 和 Flink 用 yyyy-MM-dd HH:mm:ss,MaxCompute 不支持格式参数。
- StarRocks 对 2038-01-19 之后的时间返回 0,不报错。远期日期(例如有效期 2099-12-31)转换后会变成 0,很难发现。
WEEKOFYEAR 一年中的第几周
- Hologres 的 EXTRACT 返回 DOUBLE PRECISION,直接拼接字符串会得到 12.0 这类结果,需要先 CAST 成整数。
- StarRocks 文档没有写明 WEEKOFYEAR 的周规则。需要和其他引擎对齐时,建议改用 week_iso 并实测。
可以直接用的函数
下面 20 个函数在两个引擎中写法相同。参数、返回值和边界情况仍可能不同,点开函数页查看细节。
- APPROX_COUNT_DISTINCT 近似去重计数
- ARRAY_CONTAINS 判断数组是否包含元素
- COALESCE 取第一个非空值
- COLLECT_LIST 聚合为数组
- COLLECT_SET 去重聚合为数组
- CONCAT 字符串拼接
- CONCAT_WS 按分隔符拼接
- DATEDIFF 日期差
- DATETRUNC 日期截断
- DECODE 多值匹配
- EXPLODE 数组展开为多行
- GET_JSON_OBJECT 提取 JSON 字段
- GETDATE 获取当前时间
- IF 条件判断
- LAST_DAY 当月最后一天
- MAX_BY 取最大值对应的列
- REGEXP_REPLACE 正则替换
- SIZE 数组和 Map 元素个数
- SORT_ARRAY 数组排序
- SPLIT_PART 按分隔符取第 N 段