首页 / 工具 / 迁移清单 / Doris → Hologres
Doris 迁移到 Hologres 的函数改写清单
从 Doris 迁移到 Hologres 时,在 Doris 有对应写法的 44 个常用函数中,28 个需要改写(其中 2 个在 Hologres 没有对应函数)。逐个列出两边写法和注意事项。
需要改写的函数 · 迁移注意事项 · 可以直接用的函数 · 反向:Hologres 迁移到 Doris
需要改写的函数
| 函数 | Doris 写法 | Hologres 写法 | Hologres 说明 |
|---|---|---|---|
| ADD_MONTHS | MONTHS_ADD(date, nums) | 需改写 d + interval '1 month' | ADD_MONTHS 是 Oracle 兼容函数,需要先加载 orafce 扩展。原生写法用 interval 加减。 |
| ANY_VALUE | ANY_VALUE(expr) | 需改写 MAX(col) | 通用聚合函数中没有 ANY_VALUE。组内值都相同时,可以用 MAX 或 MIN 代替。 |
| COLLECT_LIST | COLLECT_LIST(expr[, max_size]) | 需改写 ARRAY_AGG(expression) | 没有 COLLECT_LIST,用 ARRAY_AGG。 |
| COLLECT_SET | COLLECT_SET(expr[, max_size]) | 需改写 ARRAY_AGG(DISTINCT expression) | 没有 COLLECT_SET,用 ARRAY_AGG。不支持 JSON、JSONB、INTERVAL 和数组等类型。 |
| DATE_ADD | DATE_ADD(date, INTERVAL n DAY) | 需改写 DATEADD(d, num, 'day') | 文档中没有 DATE_ADD,可以用 DATEADD 或 d + interval。DATEADD 需要 V2.0.31~V2.1.0 或 V2.1.13 及以上版本。 |
| DATE_FORMAT | DATE_FORMAT(date, '%Y-%m-%d %H:%i:%s') | 需改写 TO_CHAR(timestamp, 'YYYY-MM-DD HH24:MI:SS') | 文档中没有 DATE_FORMAT,用 TO_CHAR 代替。格式符是 PostgreSQL 风格,HH 默认是 12 小时制,24 小时制要写 HH24。 |
| DATE_SUB | DATE_SUB(date, INTERVAL n DAY) | 需改写 d - interval '1 day' | 文档中没有 DATE_SUB。可以用日期减 interval,也可以写 DATEADD(d, -n, 'dd')。DATEADD 需要 V2.0.31~V2.1.0 或 V2.1.13 及以上版本。 |
| DATEADD | TIMESTAMPADD(unit, n, datetime_expr) | 支持 DATEADD(d, num, str) | 需要 V2.0.31~V2.1.0 或 V2.1.13 及以上版本。单位写法与 MaxCompute 一致,包括 yyyy、mm、dd、hh、mi、ss。默认只支持 1925~2282 年,并且暂不支持常量入参写入。 |
| DAYOFWEEK | DAYOFWEEK(date) | 需改写 EXTRACT(DOW FROM ts) + 1 | DOW 以周日为 0,所以要加 1 才和其他引擎一致。ISODOW 以周一为 1、周日为 7。 |
| EXPLODE | LATERAL VIEW EXPLODE(arr) t AS x | 需改写 UNNEST(anyarray) | 把数组的每个元素展开成一行。 |
| FROM_JSON | JSON_PARSE(json_str) | 需改写 json_str::jsonb ->> 'key' | 没有 FROM_JSON。先转成 JSON 或 JSONB,再用 -> 或 ->> 取字段,->> 返回 TEXT。需要展开成多列时可以用 json_populate_record。 |
| FROM_UNIXTIME | FROM_UNIXTIME(unix_timestamp[, string_format]) | 需改写 TO_TIMESTAMP(seconds) | 文档中没有 FROM_UNIXTIME。TO_TIMESTAMP(double precision) 按秒转换,返回 TIMESTAMPTZ。需要字符串时再用 TO_CHAR。 |
| GET_JSON_OBJECT | GET_JSON_STRING(json_str, json_path) | 支持 GET_JSON_OBJECT(json, json_path) | 属于 hive_compatible 扩展,使用前需要先执行 CREATE EXTENSION。 |
| INSTR | INSTR(str, substr) | 需改写 STRPOS(str, substr) | INSTR 是 Oracle 兼容函数,需要先安装 orafce 扩展才能用,支持起始位置和第 N 次出现。不装扩展时用 STRPOS。 |
| LENGTH | CHAR_LENGTH(str) | 支持 LENGTH(str) | 按 UTF-8 字符计数,一个汉字、数字或字母都算 1,结果与 CHAR_LENGTH 相同。字节数用 OCTET_LENGTH。 |
| MONTHS_BETWEEN | MONTHS_BETWEEN(end, start[, round_type]) | 需改写 (EXTRACT(YEAR FROM a) - EXTRACT(YEAR FROM b)) * 12 + EXTRACT(MONTH FROM a) - EXTRACT(MONTH FROM b) | 日期函数中没有 MONTHS_BETWEEN,可以用 EXTRACT 取年和月计算整数月差,不含小数部分。 |
| NVL | NVL(expr1, expr2) | 需改写 COALESCE(value, default_value) | 条件函数文档中没有 NVL,只有 COALESCE、IF、NULLIF 等,需要改写为 COALESCE。 |
| PERCENTILE_APPROX | PERCENTILE_APPROX(col, p[, compression]) | 需改写 APPROX_PERCENTILE(p) WITHIN GROUP (ORDER BY col) | Hologres V3.1 起提供,用蓄水池抽样计算,最多保留 8,192 个元素。p 是 0~1 之间的常量。 |
| REGEXP_EXTRACT | REGEXP_EXTRACT(str, pattern, pos) | 需改写 (REGEXP_MATCH(str, pattern))[n] | 字符串函数中没有 REGEXP_EXTRACT。REGEXP_MATCH 返回由各分组组成的数组,再用数组下标取第 n 组,下标从 1 开始。 |
| SIZE | ARRAY_SIZE(arr) / MAP_SIZE(m) | 需改写 ARRAY_LENGTH(arr, 1) | 第二个参数是维度,从 1 开始,一维数组传 1。数组函数文档只覆盖 ARRAY。 |
| SPLIT | SPLIT_BY_STRING(str, separator) | 需改写 REGEXP_SPLIT_TO_ARRAY(str, pattern) | 字符串函数中没有 SPLIT。拆成数组用 REGEXP_SPLIT_TO_ARRAY,只取第 n 段用 SPLIT_PART(str, delimiter, n)。 |
| STR_TO_MAP | STR_TO_MAP(str[, pair_delimiter[, key_value_delimiter]]) | 不支持 | 字符串函数中没有 STR_TO_MAP。 |
| SUBSTRING_INDEX | SUBSTRING_INDEX(content, delimiter, field) | 不支持 | 字符串函数中没有 SUBSTRING_INDEX。只取某一段时可以用 SPLIT_PART。 |
| TO_CHAR | DATE_FORMAT(date, '%Y-%m-%d %H:%i:%s') | 支持 TO_CHAR(ts, 'YYYY-MM-DD HH24:MI:SS') | 格式符沿用 PostgreSQL 风格。HH 默认是 12 小时制,24 小时制要写 HH24。默认只支持 1925~2282 年。 |
| TO_DATE | str_to_date(str, format) | 支持 TO_DATE(text, format) | PostgreSQL 风格格式符,例如 YYYY-MM-DD。文档写的返回类型是 TEXT,但示例结果是日期,建议实测。 |
| UNIX_TIMESTAMP | UNIX_TIMESTAMP([date[, fmt]]) | 需改写 EXTRACT(EPOCH FROM ts) | 日期函数中没有 UNIX_TIMESTAMP。EXTRACT 的 epoch 字段返回秒数,类型是 DOUBLE PRECISION。 |
| WEEKOFYEAR | WEEKOFYEAR(date) | 需改写 EXTRACT(WEEK FROM ts) | 也可以用 week_iso(ts),文档说明语义与 EXTRACT(WEEK FROM ts) 相同、性能更好。返回 DOUBLE PRECISION。 |
| WM_CONCAT | GROUP_CONCAT([DISTINCT] str[, sep] [ORDER BY ...]) | 需改写 STRING_AGG(expression, delimiter) | 分隔符写在后面,只拼接非 NULL 值。 |
迁移注意事项
ADD_MONTHS 按月加减
- 月末日期:StarRocks、Doris 和 Spark 在目标月份没有对应日期时取当月最后一天。StarRocks 文档特别说明,2022-02-28 加 1 个月得到 3 月 28 日而不是 3 月 31 日,这和 Oracle 的行为不同。
- Hologres 和 Flink 的月末行为文档没有写明,迁移涉及月末日期时建议用已知数据核对。
ANY_VALUE 取组内任意值
- NULL 的处理不同:MaxCompute 和 Doris 会优先返回非 NULL 值,Spark 默认可能返回 NULL,需要传 true 才会跳过 NULL。
COLLECT_LIST 聚合为数组
- StarRocks 的 ARRAY_AGG 保留 NULL,MaxCompute 和 Doris 的 COLLECT_LIST 丢弃 NULL,数组长度可能不一致。
COLLECT_SET 去重聚合为数组
- NULL 的处理不同:MaxCompute、Doris 会丢弃 NULL,StarRocks 的 ARRAY_AGG 会保留 NULL。迁移到 StarRocks 后数组里可能多出 NULL 元素。
- Doris 的 max_size 截断时保留哪些元素,文档没有说明,不要依赖它取“前 N 个”。
DATE_FORMAT 日期格式化
- Hologres 的 HH 默认是 12 小时制,下午的时间会少 12 小时,必须写 HH24。
- StarRocks 和 Doris 中 %m 是月、%i 是分钟,写成 %M 会输出英文月份名。
DATE_SUB 日期减天数
- 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 分钟,是迁移时最常见的错误。
- Hologres 的 DATEADD 默认只支持 1925~2282 年。9999-12-31 这类表示“永久有效”的日期需要单独处理。
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)。
EXPLODE 数组展开为多行
- 空数组和 NULL 数组的行会被直接丢掉:MaxCompute、Doris 的 EXPLODE 和 StarRocks 的 UNNEST 都是这样。需要保留时,Doris 和 Spark 用 EXPLODE_OUTER,StarRocks 3.2.7 起用 LEFT JOIN UNNEST(...) ON TRUE。
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 年以前的时间无法用这个函数转换。
GET_JSON_OBJECT 提取 JSON 字段
- Hologres 报错 function get_json_object (text, unknown) does not exist 时,常见原因有两个:RAM 用户没有扩展所在 schema 的查询权限,或者第一个参数不是 TEXT 类型。前者可以把扩展建在 pg_catalog 下,后者需要先 CAST 为 text。
- StarRocks 和 Doris 返回字符串,取出的数字需要再做 CAST。Doris 中值无法无损转换为字符串时返回 NULL。
INSTR 查找子串位置
- MaxCompute 的三参数和四参数写法,例如 INSTR(s, 'e', 3, 2),在 StarRocks、Doris、Hive、Spark 和 Flink 中都没有对应写法。只传起始位置时可以改成 LOCATE,取第 N 次出现时需要改写成多步计算。
- Hologres 的 INSTR 依赖 orafce 扩展。没有安装扩展时 SQL 会报函数不存在,改用 STRPOS 即可。
- 子串为空串时,MaxCompute 和 Doris 文档写明返回 1,其他引擎文档没有说明。用 INSTR(s, x) > 0 判断包含关系时,x 可能为空串的场景要单独处理。
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 个月判断)需要重新设计。
- 时间部分的处理不同:Doris 只看日期,Hive 会把时间部分算进小数,Spark 在同一天或都是月末时忽略时间。同样的输入可能得到不同的小数。
- 舍入不同:Hive 和 Spark 默认保留 8 位小数,MaxCompute 返回完整的 DOUBLE,Doris 由 round_type 控制。和原结果做等值比较前,先统一 ROUND。
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 判断的逻辑迁移后要实测。
- Doris 默认用 RE2 语法,不支持 (?=...) 这类零宽断言。从 Hive 或 Spark 的 Java 正则迁移过来时,需要先确认是否用到这些写法。
SIZE 数组和 Map 元素个数
- StarRocks 和 Doris 区分数组和 Map 函数。从 MaxCompute 或 Hive 迁移时,要按字段类型分别改成 array_length、map_size 或 ARRAY_SIZE、MAP_SIZE。
- Hologres 文档中 ARRAY_LENGTH 的签名带维度参数,一维数组也要写成 ARRAY_LENGTH(arr, 1)。
- StarRocks 和 Doris 文档写明 NULL 元素也计入个数。需要只统计非空元素时,要先过滤再计数。
SPLIT 字符串拆分
- 只需要取某一段时,Hologres 的 SPLIT_PART 和 Flink 的 SPLIT_INDEX 更直接。注意 SPLIT_PART 的序号从 1 开始,SPLIT_INDEX 为负数时返回 NULL。
STR_TO_MAP 字符串转 Map
- 默认的键值分隔符不同:MaxCompute 和 Flink 是等号,StarRocks、Doris、Hive 和 Spark 是冒号。省略分隔符的写法迁移后会解析出错误结果,而且不会报错。
- Hologres 没有 STR_TO_MAP。可以先用 REGEXP_SPLIT_TO_ARRAY 拆分,再按需取值,或者在入库前把数据转成 JSON。
SUBSTRING_INDEX 按分隔符截取
- count 为 0 时结果不同:StarRocks 返回 NULL,Doris 返回空字符串,其他引擎文档没有说明。
- Hologres 和 Flink 没有这个函数。只取某一段可以改用 Hologres 的 SPLIT_PART 或 Flink 的 SPLIT_INDEX;要取“前两段”这种跨分隔符的结果,需要拼接或用正则改写。
- 从 URL 中取域名这类场景常写成 substring_index(substring_index(url, '/', 3), '/', -1),嵌套写法在 Hologres 和 Flink 中要整体改写。
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。
UNIX_TIMESTAMP 日期转时间戳
- 格式参数的写法不同:StarRocks 和 Doris 用 %Y-%m-%d %H:%i:%s,Hive、Spark 和 Flink 用 yyyy-MM-dd HH:mm:ss,MaxCompute 不支持格式参数。
- Doris 传入格式参数时返回 DECIMAL 而不是整数,写入 BIGINT 列前需要 CAST。
WEEKOFYEAR 一年中的第几周
- Hologres 的 EXTRACT 返回 DOUBLE PRECISION,直接拼接字符串会得到 12.0 这类结果,需要先 CAST 成整数。
WM_CONCAT 分组拼接字符串
- 分隔符的位置相反:WM_CONCAT 写在第一个参数,STRING_AGG、GROUP_CONCAT(Doris)和 LISTAGG 写在最后。直接替换函数名会把分隔符当成要拼接的值。
- 不写排序时,各引擎拼接的顺序都不固定。需要稳定结果时,MaxCompute 写 WITHIN GROUP (ORDER BY ...),StarRocks 和 Doris 在 GROUP_CONCAT 内写 ORDER BY。
可以直接用的函数
下面 16 个函数在两个引擎中写法相同。参数、返回值和边界情况仍可能不同,点开函数页查看细节。