DuckDB分析实例兼容性说明

更新时间:
复制为 MD 格式

本文介绍RDS MySQL DuckDB分析实例的兼容性。

说明

以下兼容性说明内容均需开启duckdb_sql_normalization参数。

支持的数据类型

在下表中,仅列出DuckDB分析实例与MySQL存在差异的数据类型

类型

MySQL数据类型

兼容性说明

字符类型

CHARVARCHAR

仅支持UTF8系列的字符集和校对规则。

时间类型

TIME

DuckDB分析实例支持范围为'00:00:00'~'23:59:59',数据格式为'HH:MM:SS'

MySQL支持范围为'-838:59:59'~'838:59:59'。由于两者在取值范围上存在差异,若数据不在DuckDB分析实例支持范围内,可能导致查询结果不一致。

DATE

DuckDB分析实例支持范围为'0001-01-01'~'9999-12-31',数据格式为'YYYY-MM-DD'

对于范围在'0000-00-00'~'0001-01-01'的数据,MySQL支持但DuckDB不支持,查询结果可能不一致。

DATETIME

DuckDB分析实例支持范围为'0001-01-01 00:00:00.000000' UTC~'9999-12-31 00:00:00.999999' UTC,数据格式为'YYYY-MM-DD HH:MM:SS.MS'

对于范围在'0000-00-00 00:00:00'~'0001-01-01 00:00:00'的数据,MySQL支持但DuckDB不支持,查询结果可能不一致。

空间数据类型

GEOMETRYPOINTLINESTRINGPOLYGONMULTIPOINTMULTILINESTRINGMULTIPOLYGONGEOMETRYCOLLECTION

不兼容

SELECT语句限制

  • 字符集转换

    对于字符集转换函数,无论目标字符集为何值,都将统一转换为utf8mb4字符集交由DuckDB执行。例如:

    SELECT convert(id using gbk) FROM t1;
    SELECT cast(id AS CHAR CHARACTER SET utf8mb4) FROM t1;
  • 时间间隔单位(Interval unit)

    不支持以下时间间隔单位。

    YEAR_MONTH, DAY_HOUR, HOUR_MINUTE, DAY_MINUTE, HOUR_SECOND, DAY_SECOND, SECOND_MICROSECOND, HOUR_MICROSECOND, DAY_MICROSECOND, MINUTE_SECOND, MINUTE_MICROSECOND, SQL_TSI_HOUR
  • 子查询

    不支持等值非标量子查询。例如:

    SELECT * FROM t1 WHERE (id, col1) = (SELECT id, col1 FROM t1);
  • BINARY(num)类型转换

    不支持显式转换为BINARY(num)数据类型,其中的binary位数将被忽略。例如:

    SELECT CAST('abc' AS binary(1));
  • UNSIGNED类型转换

    不支持显式转换为UNSIGNED数据类型。例如:

    SELECT CAST(1 AS UNSIGNED);

类型转换问题

为确保执行效率,DuckDB分析实例在执行过程中采用强类型约束机制。在查询执行时,系统会根据上下文自动进行类型转换,这种转换称为隐式类型转换。对于无法通过隐式方式完成转换的场景,您需要使用CASTCONVERT函数显式指定类型转换,以确保查询能够正确执行。

函数中支持的隐式类型转换规则

说明
  • “/”表示不涉及隐式转换,“✔️”表示支持隐式转换,“✖️”表示不支持隐式转换。

  • 常规字符串类型代指MySQL中的CHARVARCHARTINYTEXTTEXTMEDIUMTEXTLONGTEXTJSONSETENUM

  • 二进制字符串类型代指MySQL中的BINARYVARBINARYBITTINYBLOBBLOBMEDIUMBLOBLONGBLOB

  • 不支持大范围整数类型转换为小范围整数类型。

转换至基础标量类型

源类型

隐式转换至基础标量类型

字符串字面量

数值字面量

基础标量

字符串字面量

/

✖️

数值字面量

✖️

/

数值

BOOLEAN

✖️

✖️

整数类型

✖️

✖️

FLOAT

✖️

✖️

DOUBLE

✖️

✖️

DECIMAL

✖️

✖️

字符串

常规字符串

✖️

✖️

二进制字符串

✖️

✖️

日期与时间

YEAR

✖️

✖️

DATE

✖️

✖️

TIME

✖️

✖️

DATETIME

✖️

✖️

TIMESTAMP

✖️

✖️

转换至数值类型

源类型

隐式转换至数值类型

BOOLEAN

整数类型

FLOAT

DOUBLE

DECIMAL

基础标量

字符串字面量

✖️

✖️

✖️

✔️

✖️

数值字面量

✖️

✔️

✔️

✔️

✔️

数值

BOOLEAN

/

✖️

✖️

✖️

✖️

整数类型

✖️

/

✔️

✔️

✔️

FLOAT

✖️

✔️:仅支持转换为BIGINT

/

✔️

✖️

DOUBLE

✖️

✔️:仅支持转换为BIGINT

✖️

/

✖️

DECIMAL

✖️

✔️

✔️

✔️

/

字符串

常规字符串

✖️

✖️

✖️

✔️

✖️

二进制字符串

✖️

✖️

✖️

✖️

✖️

日期与时间

YEAR

✖️

✔️

✔️

✔️

✔️

DATE

✖️

✖️

✖️

✔️

✖️

TIME

✖️

✖️

✖️

✔️

✖️

DATETIME

✖️

✖️

✖️

✔️

✖️

TIMESTAMP

✖️

✖️

✖️

✔️

✖️

转换至字符串类型

源类型

隐式转换至字符串类型

常规字符串

二进制字符串

基础标量

字符串字面量

✔️

✖️

数值字面量

✖️

✖️

数值

BOOLEAN

✖️

✖️

整数类型

✔️

✖️

FLOAT

✔️

✖️

DOUBLE

✔️

✖️

DECIMAL

✔️

✖️

字符串

常规字符串

/

✖️

二进制字符串

✖️

/

日期与时间

YEAR

✔️

✖️

DATE

✔️

✖️

TIME

✔️

✖️

DATETIME

✔️

✖️

TIMESTAMP

✔️

✖️

转换至日期与时间类型

源类型

隐式转换至日期与时间类型

YEAR

DATE

TIME

DATETIME

TIMESTAMP

基础标量

字符串字面量

✖️

✖️

✖️

✖️

✖️

数值字面量

✔️

✖️

✖️

✖️

✖️

数值

BOOLEAN

✖️

✖️

✖️

✖️

✖️

整数类型

✖️

✖️

✖️

✖️

✖️

FLOAT

✖️

✖️

✖️

✖️

✖️

DOUBLE

✖️

✖️

✖️

✖️

✖️

DECIMAL

✖️

✖️

✖️

✖️

✖️

字符串

常规字符串

✖️

✖️

✖️

✖️

✖️

二进制字符串

✖️

✖️

✖️

✖️

✖️

日期与时间

YEAR

/

✖️

✖️

✖️

✖️

DATE

✖️

/

✖️

✔️

✔️

TIME

✖️

✖️

/

✔️

✔️

DATETIME

✖️

✖️

✖️

/

✔️

TIMESTAMP

✖️

✖️

✖️

✔️

/

类型比较中支持的隐式转换规则

DuckDB分析实例在类型转换和比较规则上具有更高的严格性和一致性,但在某些场景下可能与MySQL存在行为差异。具体如下:

  • 字符串到日期的隐式转换:字符串隐式转换为日期时,如果字符串格式无法正确解析为有效的日期值,SQL查询将报错并执行失败。

  • 整数类型之间的比较规则:不同整数类型之间进行比较时,DuckDB分析实例会统一向取值范围更大的整数类型进行转换。

  • 多元表达式的类型转换顺序:对于col1 in (col2, col3, col4, ...)、col1 between col2 and col3、coalesce(col1, col2, col3, ...)等多元表达式,会按照顺序进行类型转换。

  • YEAR类型的兼容性差异:在DuckDB分析实例中,YEAR类型会被转换为INTEGER类型进行比较,可能与MySQL存在不兼容。例如:

    CREATE TABLE t1 (id YEAR PRIMARY KEY);
    INSERT INTO t1 VALUES (1980);
    SELECT * FROM t1 WHERE id BETWEEN 70 AND 90;
    
    # MySQL查询结果
    +------+
    | id   |
    +------+
    | 1980 |
    +------+
    
    # DuckDB分析实例查询结果
    Empty set.
  • 布尔类型的字符串转换规则:DuckDB分析实例支持将'1'、'0'、'yes'、'no'、'true'、'false'六种字符串转换为BOOLEAN类型,其余字符串转换会报错;而MySQL会将'1'转换为true,其余字符串均转换为false。因此,如下SQL可能会存在结果不一致问题:

    CREATE TABLE t1 (id INT PRIMARY KEY);
    INSERT INTO t1 VALUES (1);
    SELECT id FROM t1 WHERE 'true';
    
    # MySQL查询结果
    Empty set
    
    # DuckDB分析实例查询结果
    +------+
    | id   |
    +------+
    |    1 |
    +------+
说明
  • 当不同类型的数据进行比较时,系统会按下表规则,将数据“转换为同一类型”后进行比较;对于不支持(✖️)的类型比较,会直接报错。

  • 常规字符串类型代指MySQL中的CHARVARCHARTINYTEXTTEXTMEDIUMTEXTLONGTEXTJSONSETENUM

  • 二进制字符串类型代指MySQL中的BINARYVARBINARYBITTINYBLOBBLOBMEDIUMBLOBLONGBLOB

与基础标量类型比较

源类型

与基础标量类型比较

字符串字面量

数值字面量

基础标量

字符串字面量

字符串

数值字面量

数值字面量

数值字面量

较大范围的数值类型

数值

BOOLEAN

BOOLEAN

较大范围的数值类型

整数类型

整数类型

较大范围的数值类型

FLOAT

FLOAT

较大范围的数值类型

DOUBLE

DOUBLE

较大范围的数值类型

DECIMAL

DECIMAL

较大范围的数值类型

字符串

常规字符串

常规字符串

数值字面量

二进制字符串

二进制字符串

✖️

日期与时间

YEAR

YEAR

较大范围的数值类型

DATE

DATETIME

✖️

TIME

TIME

✖️

DATETIME

DATETIME

✖️

TIMESTAMP

TIMESTAMP

✖️

与数值类型比较

源类型

与数值类型比较

BOOLEAN

整数类型

FLOAT

DOUBLE

DECIMAL

基础标量

字符串字面量

BOOLEAN

整数类型

FLOAT

DOUBLE

DECIMAL

数值字面量

较大范围的数值类型

较大范围的数值类型

较大范围的数值类型

较大范围的数值类型

较大范围的数值类型

数值

BOOLEAN

BOOLEAN

整数类型

FLOAT(不等式比较✖️)

DOUBLE(不等式比较✖️)

DECIMAL(不等式比较✖️)

整数类型

整数类型

整数类型

FLOAT

DOUBLE

DECIMAL

FLOAT

FLOAT(不等式比较✖️)

FLOAT

FLOAT

DOUBLE

FLOAT

DOUBLE

DOUBLE(不等式比较✖️)

DOUBLE

DOUBLE

DOUBLE

DOUBLE

DECIMAL

DECIMAL(不等式比较✖️)

DECIMAL

FLOAT

DOUBLE

DECIMAL

字符串

常规字符串

BOOLEAN

整数类型

FLOAT

DOUBLE

DECIMAL

二进制字符串

✖️

✖️

✖️

✖️

✖️

日期与时间

YEAR

INTEGER

较大范围的整数类型

FLOAT

DOUBLE

DECIMAL

DATE

✖️

✖️

✖️

DOUBLE

✖️

TIME

✖️

✖️

✖️

DOUBLE

✖️

DATETIME

✖️

✖️

✖️

DOUBLE

✖️

TIMESTAMP

✖️

✖️

✖️

DOUBLE

✖️

与字符串类型比较

源类型

与字符串类型比较

常规字符串

二进制字符串

基础标量

字符串字面量

常规字符串

二进制字符串

数值字面量

数值字面量

✖️

数值

BOOLEAN

BOOLEAN

✖️

整数类型

整数类型

✖️

FLOAT

FLOAT

✖️

DOUBLE

DOUBLE

✖️

DECIMAL

DECIMAL

✖️

字符串

常规字符串

常规字符串

二进制字符串

二进制字符串

二进制字符串

二进制字符串

日期与时间

YEAR

INTEGER

✖️

DATE

DATE

✖️

TIME

TIME

✖️

DATETIME

DATETIME

✖️

TIMESTAMP

TIMESTAMP

✖️

与日期与时间类型比较

源类型

与日期与时间类型比较

YEAR

DATE

TIME

DATETIME

TIMESTAMP

基础标量

字符串字面量

YEAR

DATETIME

TIME

DATETIME

TIMESTAMP

数值字面量

较大范围的数值类型

✖️

✖️

✖️

✖️

数值

BOOLEAN

INTEGER

✖️

✖️

✖️

✖️

整数类型

较大范围的整数类型

✖️

✖️

✖️

✖️

FLOAT

FLOAT

✖️

✖️

✖️

✖️

DOUBLE

DOUBLE

DOUBLE

DOUBLE

DOUBLE

DOUBLE

DECIMAL

DECIMAL

✖️

✖️

✖️

✖️

字符串

常规字符串

INTEGER

DATE

TIME

DATETIME

TIMESTAMP

二进制字符串

✖️

✖️

✖️

✖️

✖️

日期与时间

YEAR

INTEGER

✖️

✖️

✖️

✖️

DATE

✖️

DATE

✖️

DATETIME

TIMESTAMP

TIME

✖️

✖️

TIME

✖️

✖️

DATETIME

✖️

DATETIME

✖️

DATETIME

DATETIME

TIMESTAMP

✖️

TIMESTAMP

✖️

DATETIME

TIMESTAMP

可能出现的查询结果不一致问题

数值运算

  • 浮点数的大小比较存在不兼容。例如:

    CREATE TABLE t1 (id FLOAT PRIMARY KEY);
    INSERT INTO t1 VALUES (1.22), (1.23), (1.24);
    SELECT * FROM t1 WHERE t1.id > 1.23;
    
    # MySQL查询结果
    +------+
    | id   |
    +------+
    | 1.23 |
    | 1.24 |
    +------+
    
    # DuckDB分析实例查询结果
    +------+
    | id   |
    +------+
    | 1.24 |
    +------+
  • 浮点数的复杂复合运算结果因为浮点误差会存在不一致。

  • 当整数、DECIMAL类型之间做运算时,结果不能超过该类型的取值范围,否则可能出现结果溢出导致的执行失败。

    CREATE TABLE t1 (id TINYINT PRIMARY KEY);
    INSERT INTO t1 VALUES (100);
    SELECT id * 2 FROM t1;
    
    # MySQL查询结果
    +--------+
    | id * 2 |
    +--------+
    |    200 |
    +--------+
    
    # DuckDB分析实例查询结果
    ERROR 7577 (HY000): [DuckDB] Out of Range Error: Overflow in multiplication of INT8 (100 * 2)!.

校对规则导致的结果不一致问题

utf8mb4_0900_xx系列的校对规则在部分符号字符的比较中存在不兼容。例如:

CREATE TABLE t1 ( id varchar(20) COLLATE utf8mb4_0900_ai_ci PRIMARY KEY );
INSERT INTO t1 VALUES ('!'), ('_');
SELECT * FROM t1 ORDER BY id;

# MySQL查询结果
+----+
| id |
+----+
| _  |
| !  |
+----+

# DuckDB分析实例查询结果
+----+
| id |
+----+
| !  |
| _  |
+----+

IN的向量子查询对于NULL值的处理

DuckDB分析实例中,IN的向量子查询对于NULL值的处理存在不兼容问题。例如:

CREATE TABLE t1 (id INT PRIMARY KEY, col1 INT);
INSERT INTO t1 VALUES (1, 1), (2, 2);
CREATE TABLE t2 (id INT PRIMARY KEY, col1 INT);
INSERT INTO t2 VALUES (1, NULL);

select (id, col1) in (select id, col1 from t2) from t1;

# MySQL查询结果
+-----------------------------------------+
| (id, col1) in (select id, col1 from t2) |
+-----------------------------------------+
|                                    NULL |
|                                       0 |
+-----------------------------------------+

# DuckDB分析实例查询结果
+-----------------------------------------+
| (id, col1) in (select id, col1 from t2) |
+-----------------------------------------+
|                                    NULL |
|                                    NULL |
+-----------------------------------------+

对于数据(2, 2),IN后不存在向量前缀的匹配项,MySQL返回0,DuckDB分析实例返回NULL。

函数限制

在下表中,仅列出DuckDB分析实例与MySQL存在兼容性差异的函数

聚合函数

函数名

是否支持

使用限制

BIT_AND

不支持字符串类型、DECIMAL类型、日期类型。

BIT_OR

不支持字符串类型、DECIMAL类型、日期类型。

BIT_XOR

不支持字符串类型、DECIMAL类型、日期类型。

JSON_ARRAYAGG

/

数值函数

数值函数不支持BOOLEAN类型。

函数名

是否支持

使用限制

CONV()

/

CRC32()

/

TRUNCATE()

/

字符串函数

MySQL DuckDB严格区分二进制字符串(BLOBVARBINARY等)和字符串(VARCHAR,TEXT,JSON等),因此以下字符串函数使用限制只考虑以字符串为输入,不以二进制字符串为输入。部分能够以二进制字符串为输入的函数有:CONCAT()CONCAT_WS()LENGTH()MID()OCTET_LENGTH()REPEAT()TO_BASE64(),对于这些函数,如果没有额外说明,则无使用限制。

函数名

是否支持

使用限制

BIN()

MySQLBIN('')返回NULL,DuckDB分析实例返回'0'

CHAR()

/

ELT()

/

EXPORT_SET()

/

FIND_IN_SET()

该函数的第一个参数需要是字符类型,非字符类型可能会产生与MySQL不一致的结果。

FORMAT()

/

FROM_BASE64()

该函数使用base64解码规则解码失败时会报错。

LIKE

LIKE不受校对规则的影响。

LOAD_FILE()

/

MAKE_SET()

/

MATCH()

/

NOT LIKE

NOT LIKE不受校对规则的影响。

OCT()

MySQLOCT('')返回NULL,DuckDB分析实例返回'0'

QUOTE()

/

SOUNDEX()

/

SOUND LIKE

/

UNHEX()

该函数遇到非HEX digit会报错。

WEIGHT_STRING()

/

日期函数

函数名

是否支持

使用限制

ADDTIME()

如果返回值超出DuckDB分析实例的时间类型数据的取值范围,会产生结果不一致的问题。

DATE_FORMAT()

不支持%X%V%u

GET_FORMAT()

/

PERIOD_ADD()

年份超过9999暂不支持。

PERIOD_DIFF()

年份超过9999暂不支持。

SEC_TO_TIME()

如果返回值超出DuckDB分析实例的时间类型数据的取值范围,会产生结果不一致的问题。

STR_TO_DATE()

  • 不支持%X%V%u

  • 如果存在format specifier没有被正确匹配,则返回NULL。

SUBTIME()

如果返回值超出DuckDB分析实例的时间类型数据的取值范围,会产生结果不一致的问题。

TIME_TO_SEC()

不支持DAY TIME格式的输入,例如:select time_to_sec('1 12:00:00');

TIMEDIFF()

/

JSON函数

函数名

是否支持

使用限制

JSON_ARRAY_APPEND()

/

JSON_ARRAY_INSERT()

/

JSON_INSERT()

/

JSON_MERGE()

/

JSON_MERGE_PATCH()

合并后JSON的字段顺序可能与MySQL中不同。

JSON_MERGE_PRESERVE()

/

JSON_REMOVE()

/

JSON_REPLACE()

/

JSON_SCHEMA_VALID()

/

JSON_SCHEMA_VALIDATION_REPORT()

/

JSON_SEARCH()

/

JSON_SET()

/

JSON_STORAGE_FREE()

/

JSON_STORAGE_SIZE()

/

JSON_TABLE()

/

JSON_TYPE()

/

窗口函数

函数名

是否支持

使用限制

JSON_ARRAYAGG

/

JSON_OBJECTAGG

/