首页 / 工具 / 迁移清单 / Doris → MaxCompute
Doris 迁移到 MaxCompute 的函数改写清单
从 Doris 迁移到 MaxCompute 时,在 Doris 有对应写法的 44 个常用函数中,15 个需要改写,另有 1 个可以改用 MaxCompute 的原生函数。逐个列出两边写法和注意事项。
需要改写的函数 · 可以改用原生函数 · 迁移注意事项 · 可以直接用的函数 · 反向:MaxCompute 迁移到 Doris
需要改写的函数
| 函数 | Doris 写法 | MaxCompute 写法 | MaxCompute 说明 |
|---|---|---|---|
| ADD_MONTHS | MONTHS_ADD(date, nums) | 支持 ADD_MONTHS(startdate, num_months) | 返回 yyyy-mm-dd 格式的 STRING,不是 DATE。格式不对时返回 NULL,例如 '20170214'。 |
| APPROX_COUNT_DISTINCT | APPROX_COUNT_DISTINCT(expr) | 别名 APPROX_DISTINCT(colname) | MaxCompute 2.0 扩展函数,返回 BIGINT,文档写明会有 5% 的误差。 |
| DATEADD | TIMESTAMPADD(unit, n, datetime_expr) | 支持 DATEADD(date, delta, datepart) | datepart 必须是常量,可选 yyyy、q、mm、week、dd、hh、mi、ss、ff3 等。返回类型与 date 相同。date 为 NULL 时报错,delta 或 datepart 为 NULL 时返回 NULL。2.0 数据类型版本下,字符串要先 CAST 成 DATETIME。 |
| DATETRUNC | DATE_TRUNC(datetime, 'month') | 支持 DATETRUNC(date, date_part) | 返回类型与输入相同。单位支持 yyyy、q、mm、week、isoweek、dd、hh、mi、ss、ff3,week 默认从周一开始,也可以写 week(sunday)。 |
| FROM_JSON | JSON_PARSE(json_str) | 支持 from_json(jsonStr, schema) | schema 写法与建表时的类型一致,例如 'a bigint, b double'、'array<bigint>'、'map<string,string>'。返回 ARRAY、MAP 或 STRUCT。STRUCT 的 key 区分大小写,缺失的 key 返回 NULL,类型不匹配的值会被忽略。 |
| GET_JSON_OBJECT | GET_JSON_STRING(json_str, json_path) | 支持 GET_JSON_OBJECT(json, json_path) | 返回 STRING,路径以 $ 开头,不支持正则。转义行为受 odps.sql.udf.getjsonobj.new 控制。 |
| GETDATE | NOW([precision]) | 支持 GETDATE() | 返回 DATETIME,以东八区时间为标准。同一条 SQL 中总是返回固定值,精度到秒;开启 2.0 数据类型后精度到毫秒。 |
| LENGTH | CHAR_LENGTH(str) | 支持 LENGTH(str) | 返回 BIGINT,输入不是 UTF-8 编码时返回 -1。按字节计算长度要用 LENGTHB。 |
| SIZE | ARRAY_SIZE(arr) / MAP_SIZE(m) | 支持 SIZE(array_or_map) | 同一个函数可以处理 ARRAY 和 MAP,返回 INT。 |
| SORT_ARRAY | ARRAY_SORT(arr) | 支持 SORT_ARRAY(a[, isasc]) | isasc 默认为 True,即升序,传 False 时降序。NULL 视为最小值。 |
| SPLIT | SPLIT_BY_STRING(str, separator) | 支持 SPLIT(source, delimiter[, trimTailEmpty]) | 返回 ARRAY<STRING>。分隔符支持正则表达式。trimTailEmpty 默认为 true,会去掉末尾的空字符串。任一参数为 NULL 时返回 NULL。 |
| SUBSTR | SUBSTRING(str, pos[, len]) | 支持 SUBSTR(str, start_position[, length]) | 从 1 开始计数,负数从末尾倒数。start_position 为 0 时返回空字符串;Hive 兼容模式和 BigQuery 兼容模式下按 1 处理。length 为 0 或负数时返回空字符串。 |
| TO_CHAR | DATE_FORMAT(date, '%Y-%m-%d %H:%i:%s') | 支持 TO_CHAR(date, format) | 格式符为 yyyy、mm、dd、hh、mi、ss,也支持 %Y、%m 这类写法。日期输入时 format 必填。date 为 NULL 时报错,format 为 NULL 时返回 NULL。也可以传入 BIGINT、DOUBLE 等数值,直接转成字符串。 |
| TO_DATE | str_to_date(str, format) | 支持 TO_DATE(date_str[, format]) | 不传 format 时返回 DATE,传入 format 时返回 DATETIME。格式符为 yyyy、mm、dd、hh、mi、ss、ff3,format 必须包含 yyyy。 |
| WM_CONCAT | GROUP_CONCAT([DISTINCT] str[, sep] [ORDER BY ...]) | 支持 WM_CONCAT(separator, colname) | 分隔符必须是常量且写在前面。支持 DISTINCT 和 WITHIN GROUP (ORDER BY ...),值为 NULL 的行不参与计算。 |
可以改用原生函数
下面的函数在 Doris 中只能用替代写法,MaxCompute 有对应的函数。原来的写法通常仍能运行,换成原生函数会更简洁。
| 函数 | Doris 写法 | MaxCompute 写法 | MaxCompute 说明 |
|---|---|---|---|
| DECODE | CASE expr WHEN search THEN result ... ELSE default END | 支持 DECODE(expression, search, result[, search, result]...[, default]) | 没有匹配且没有 default 时返回 NULL。所有 result 的类型必须一致,search 与 expression 的类型也必须一致,否则报错。在 DECODE 中 NULL 与 NULL 视为相等。 |
迁移注意事项
ADD_MONTHS 按月加减
- 月末日期:StarRocks、Doris 和 Spark 在目标月份没有对应日期时取当月最后一天。StarRocks 文档特别说明,2022-02-28 加 1 个月得到 3 月 28 日而不是 3 月 31 日,这和 Oracle 的行为不同。
- MaxCompute 返回字符串,Hive 4.0.0 之前也会丢掉时间部分。结果和 DATE 或 DATETIME 字段比较时,注意类型转换。
APPROX_COUNT_DISTINCT 近似去重计数
- 各引擎的误差不同:MaxCompute 文档写的是 5%,Hologres 默认是 0.1%~1%。迁移后与原报表对数时,小的差异属于正常现象,不能直接当作数据问题。
DATEADD 按单位加减日期
- MaxCompute 和 Hologres 中 mm 表示月,mi 表示分钟。把 DATEADD(d, 1, 'mm') 当成加 1 分钟,是迁移时最常见的错误。
- Spark 3.4.0 起的 dateadd(d, 1) 表示加 1 天,参数个数和含义都与 MaxCompute 不同,不能直接照搬。
- MaxCompute 的 DATEADD 遇到 date 为 NULL 会报错,而不是返回 NULL。字段可能为空时,先过滤或用 IF 包一层。
- MaxCompute 按月加减时,如果目标月份没有对应日期,结果取当月最后一天。StarRocks 的 DATE_ADD 遇到不存在的日期返回 NULL。
DATETRUNC 日期截断
- 参数顺序不同:MaxCompute 是日期在前,Hologres、StarRocks 和 Spark 是单位在前,Doris 两种都接受。
- 返回类型不同:MaxCompute 对 DATE 输入返回 DATE,Hologres 和 Spark 的 date_trunc 返回时间戳。结果用于关联 DATE 字段时要先转换。
- 周的起点:MaxCompute 的 week 默认从周一开始,Doris 和 Spark 文档的示例也截断到周一。按周汇总前确认业务定义的周起点。
FROM_JSON 按 schema 解析 JSON
- MaxCompute 的 from_json 解析成 FLOAT、DOUBLE 或 DECIMAL 时不保证精度。金额类字段建议先按 STRING 取出,再 CAST 成 DECIMAL。
- 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。
- MaxCompute 的 STRUCT key 区分大小写。JSON 里是 userId、schema 里写成 userid 时,取到的是 NULL,并且不会报错。
GET_JSON_OBJECT 提取 JSON 字段
- MaxCompute 中,2021 年 1 月 21 日之前创建的项目默认会转义 JSON 保留字符,之后创建的项目保留原始字符串。新旧项目的结果可能不同,官方推荐把 odps.sql.udf.getjsonobj.new 设为 true。
- MaxCompute 每次调用都会重新解析整个 JSON。同一个字段取多个值时,频繁调用会明显变慢,可以考虑 UDTF。
- StarRocks 和 Doris 返回字符串,取出的数字需要再做 CAST。Doris 中值无法无损转换为字符串时返回 NULL。
GETDATE 获取当前时间
- MaxCompute 的 GETDATE 固定使用东八区,其他引擎的结果取决于会话或集群时区。迁移后如果时间差了 8 小时,先检查时区设置。
- 返回类型不同:MaxCompute、StarRocks 和 Doris 返回 DATETIME,Hologres 的 NOW 带时区(文档把不带时区的版本单独列为 LOCALTIMESTAMP),Flink 返回 TIMESTAMP_LTZ(3)。直接写入字符串或 DATETIME 字段时,格式可能变化。
- 精度不同:MaxCompute 默认到秒,StarRocks 和 Doris 默认到秒、可传参数到微秒,Flink 到毫秒。用当前时间做去重或比较时要注意小数部分。
- Hive 和 Spark 的 current_timestamp 可以不带括号,Doris 文档中的写法是 current_timestamp()。迁移时统一写 NOW() 更容易对齐。
LENGTH 字符串长度
- StarRocks 和 Doris 的 LENGTH 返回字节数。像 WHERE LENGTH(name) > 10 这样的条件,迁移后对中文内容会多筛出很多行,而且不会报错。
- 按字符计数统一写 CHAR_LENGTH 最稳妥:Hologres、StarRocks、Doris、Flink 都支持,Hive 2.2.0 起也支持(char_length 是 character_length 的简写)。
- MaxCompute 的 LENGTH 遇到非 UTF-8 编码的字符串返回 -1,不是 NULL。
SIZE 数组和 Map 元素个数
- StarRocks 和 Doris 区分数组和 Map 函数。从 MaxCompute 或 Hive 迁移时,要按字段类型分别改成 array_length、map_size 或 ARRAY_SIZE、MAP_SIZE。
- StarRocks 和 Doris 文档写明 NULL 元素也计入个数。需要只统计非空元素时,要先过滤再计数。
SORT_ARRAY 数组排序
- Spark 有两个排序函数:sort_array 升序时把 NULL 放在开头,array_sort 把 NULL 放在末尾。从 MaxCompute 或 Hive 迁移时应使用 sort_array,结果才一致。
- 降序的写法不同:MaxCompute 和 Spark 传第二个参数,Flink 传 ascending_order,Doris 用 ARRAY_REVERSE_SORT,Hive 和 Hologres 的函数只能升序。
SPLIT 字符串拆分
- MaxCompute、Hive 和 Spark 按正则处理分隔符。用 . 或 | 拆分时要写成 '\\.' 或 '\\|',否则会被当成正则元字符,结果出错。
- MaxCompute 默认去掉末尾的空字符串:SPLIT('a,b,c,,', ',') 返回 ["a","b","c"]。其他引擎的处理方式不一定相同,需要保留时传入 false。
SUBSTR 截取子串
- 起始位置写 0 是常见错误。MaxCompute 默认、StarRocks 和 Doris 都返回空字符串,不会报错,结果却全是空值,很难发现。MaxCompute 开启 Hive 兼容模式后又会按 1 处理,同一条 SQL 在不同模式下结果不同。
TO_CHAR 日期转字符串
- MaxCompute 的 'yyyy-mm-dd' 原样搬到 Hive、Spark 或 Flink,mm 会被当成分钟,结果类似 2026-30-14,而且不会报错。Java 风格要写 'yyyy-MM-dd'。
- StarRocks 和 Doris 的分钟是 %i,不是 %M。%M 表示英文月份名。
- MaxCompute 的 TO_CHAR 遇到 date 为 NULL 会报错,而不是返回 NULL。
TO_DATE 字符串转日期
- 同名不同义:把 MaxCompute 的 TO_DATE('20261013', 'yyyymmdd') 直接搬到 StarRocks、Doris 或 Hive 会报错或得到错误结果,需要改用 str_to_date 或 unix_timestamp。
- MaxCompute 传入 format 时返回 DATETIME 而不是 DATE。和 DATE 类型字段比较或写入 DATE 列时,注意类型转换。
- MaxCompute 的格式符里 mm 是月、mi 是分钟;Spark 和 Flink 里 MM 是月、mm 是分钟。
- MaxCompute 的日期字符串位数不对时返回 NULL,例如 '2025112' 配 'yyyymmdd'。
WM_CONCAT 分组拼接字符串
- 分隔符的位置相反:WM_CONCAT 写在第一个参数,STRING_AGG、GROUP_CONCAT(Doris)和 LISTAGG 写在最后。直接替换函数名会把分隔符当成要拼接的值。
- 不写排序时,各引擎拼接的顺序都不固定。需要稳定结果时,MaxCompute 写 WITHIN GROUP (ORDER BY ...),StarRocks 和 Doris 在 GROUP_CONCAT 内写 ORDER BY。
DECODE 多值匹配
- MaxCompute 的 DECODE 把 NULL 和 NULL 视为相等,DECODE(x, NULL, 0, 1) 在 x 为 NULL 时返回 0。改写成 CASE x WHEN NULL THEN 0 ... 永远不会匹配,要写成 CASE WHEN x IS NULL THEN 0 ...。
- Hive 和 Flink 也有 DECODE,但含义是字符集解码。把 MaxCompute 的多参数 DECODE 原样搬过去会报参数错误,必须改写成 CASE。
- MaxCompute 要求所有 result 类型一致,例如 DECODE(x, 1, 1, 2, 'b') 会报错。改写成 CASE 后各引擎的隐式转换规则不同,建议显式 CAST。
可以直接用的函数
下面 28 个函数在两个引擎中写法相同。参数、返回值和边界情况仍可能不同,点开函数页查看细节。
- ANY_VALUE 取组内任意值
- ARRAY_CONTAINS 判断数组是否包含元素
- COALESCE 取第一个非空值
- COLLECT_LIST 聚合为数组
- COLLECT_SET 去重聚合为数组
- CONCAT 字符串拼接
- CONCAT_WS 按分隔符拼接
- DATE_ADD 日期加减
- DATE_FORMAT 日期格式化
- DATE_SUB 日期减天数
- DATEDIFF 日期差
- DAYOFWEEK 星期几
- EXPLODE 数组展开为多行
- FROM_UNIXTIME 时间戳转日期
- IF 条件判断
- INSTR 查找子串位置
- LAST_DAY 当月最后一天
- MAX_BY 取最大值对应的列
- MONTHS_BETWEEN 相差月数
- NVL 空值替换
- PERCENTILE_APPROX 近似分位数
- REGEXP_EXTRACT 正则提取
- REGEXP_REPLACE 正则替换
- SPLIT_PART 按分隔符取第 N 段
- STR_TO_MAP 字符串转 Map
- SUBSTRING_INDEX 按分隔符截取
- UNIX_TIMESTAMP 日期转时间戳
- WEEKOFYEAR 一年中的第几周