This topic describes the compatibility of DuckDB-based analytical instances provided by ApsaraDB RDS for MySQL.
The following compatibility notes all require enabling the duckdb_sql_normalization parameter.
Supported data types
The following table lists only the data types where DuckDB-based analytical instances differ from MySQL.
Type | MySQL data type | Compatibility |
String types |
| Only UTF-8 character sets and collations are supported. |
Time types |
| A DuckDB-based analytical instance supports a range of MySQL supports the range |
| DuckDB-based analytical instances support a range from For the range | |
| The supported range for DuckDB-based analytical instances is For data in the range | |
Spatial data types |
| Incompatible |
Limits on SELECT statements
Character set conversion
For character set conversion functions, regardless of the target character set, all conversions are standardized to the
utf8mb4character set and handed off to DuckDB for execution. For example:SELECT convert(id using gbk) FROM t1; SELECT cast(id AS CHAR CHARACTER SET utf8mb4) FROM t1;Interval unit
The following interval units are not supported:
YEAR_MONTH, DAY_HOUR, HOUR_MINUTE, DAY_MINUTE, HOUR_SECOND, DAY_SECOND, SECOND_MICROSECOND, HOUR_MICROSECOND, DAY_MICROSECOND, MINUTE_SECOND, MINUTE_MICROSECOND, SQL_TSI_HOURSubqueries
Non-scalar subqueries with equality conditions are not supported. Example:
SELECT * FROM t1 WHERE (id, col1) = (SELECT id, col1 FROM t1);BINARY(num) type conversion
Explicit conversion to the
BINARY(num)data type is not supported, and the specified bit length will be ignored. Example:SELECT CAST('abc' AS binary(1));UNSIGNED type conversion
Explicit conversion to the
UNSIGNEDdata type is not supported. For example:SELECT CAST(1 AS UNSIGNED);
Data type conversion issues
For optimal execution efficiency, DuckDB-based analytical instances use strict type constraints during execution. When a query is executed, the system automatically performs type conversions based on the context. This type of conversion is called implicit type conversion. For scenarios where conversion cannot be completed implicitly, you must use the CAST or CONVERT function to explicitly specify the type conversion to ensure that the query executes correctly.
Rules for implicit type conversion in functions
/ indicates that no implicit conversion is involved. ✔️ indicates that implicit conversion is supported. ✖️ indicates that implicit conversion is not supported.
Regular string types refer to the following MySQL data types:
CHAR,VARCHAR,TINYTEXT,TEXT,MEDIUMTEXT,LONGTEXT,JSON,SET, andENUM.Binary string types refer to the following MySQL data types:
BINARY,VARBINARY,BIT,TINYBLOB,BLOB,MEDIUMBLOB, andLONGBLOB.Conversion from an integer type with a larger value range to an integer type with a smaller value range is not supported.
Conversion to basic scalar types
Source type | Implicit conversion to basic scalar types | ||
String literal | Numeric literal | ||
Basic scalar | String literal | / | ✖️ |
Numeric literal | ✖️ | / | |
Value | BOOLEAN | ✖️ | ✖️ |
Integer types | ✖️ | ✖️ | |
FLOAT | ✖️ | ✖️ | |
DOUBLE | ✖️ | ✖️ | |
DECIMAL | ✖️ | ✖️ | |
String | Regular string | ✖️ | ✖️ |
Binary string | ✖️ | ✖️ | |
Date and time | YEAR | ✖️ | ✖️ |
DATE | ✖️ | ✖️ | |
TIME | ✖️ | ✖️ | |
DATETIME | ✖️ | ✖️ | |
TIMESTAMP | ✖️ | ✖️ | |
Conversion to numeric types
Source type | Implicit conversion to numeric types | |||||
BOOLEAN | Integer types | FLOAT | DOUBLE | DECIMAL | ||
Basic scalar | String literal | ✖️ | ✖️ | ✖️ | ✔️ | ✖️ |
Numeric literal | ✖️ | ✔️ | ✔️ | ✔️ | ✔️ | |
Numeric | BOOLEAN | / | ✖️ | ✖️ | ✖️ | ✖️ |
Integer types | ✖️ | / | ✔️ | ✔️ | ✔️ | |
FLOAT | ✖️ | ✔️: Only conversion to BIGINT is supported. | / | ✔️ | ✖️ | |
DOUBLE | ✖️ | ✔️: Only conversion to BIGINT is supported. | ✖️ | / | ✖️ | |
DECIMAL | ✖️ | ✔️ | ✔️ | ✔️ | / | |
String | Regular string | ✖️ | ✖️ | ✖️ | ✔️ | ✖️ |
Binary string | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ | |
Date and time | YEAR | ✖️ | ✔️ | ✔️ | ✔️ | ✔️ |
DATE | ✖️ | ✖️ | ✖️ | ✔️ | ✖️ | |
TIME | ✖️ | ✖️ | ✖️ | ✔️ | ✖️ | |
DATETIME | ✖️ | ✖️ | ✖️ | ✔️ | ✖️ | |
TIMESTAMP | ✖️ | ✖️ | ✖️ | ✔️ | ✖️ | |
Conversion to string types
Source type | Implicit conversion to string types | ||
Regular string | Binary string | ||
Basic scalar | String literal | ✔️ | ✖️ |
Numeric literal | ✖️ | ✖️ | |
Numeric | BOOLEAN | ✖️ | ✖️ |
Integer types | ✔️ | ✖️ | |
FLOAT | ✔️ | ✖️ | |
DOUBLE | ✔️ | ✖️ | |
DECIMAL | ✔️ | ✖️ | |
String | Regular string | / | ✖️ |
Binary string | ✖️ | / | |
Date and time | YEAR | ✔️ | ✖️ |
DATE | ✔️ | ✖️ | |
TIME | ✔️ | ✖️ | |
DATETIME | ✔️ | ✖️ | |
TIMESTAMP | ✔️ | ✖️ | |
Conversion to date and time types
Source type | Implicit conversion to date and time types | |||||
YEAR | DATE | TIME | DATETIME | TIMESTAMP | ||
Basic scalar | String literal | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ |
Numeric literal | ✔️ | ✖️ | ✖️ | ✖️ | ✖️ | |
value | BOOLEAN | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ |
Integer types | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ | |
FLOAT | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ | |
DOUBLE | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ | |
DECIMAL | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ | |
String | Regular string | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ |
Binary string | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ | |
Date and time | YEAR | / | ✖️ | ✖️ | ✖️ | ✖️ |
DATE | ✖️ | / | ✖️ | ✔️ | ✔️ | |
TIME | ✖️ | ✖️ | / | ✔️ | ✔️ | |
DATETIME | ✖️ | ✖️ | ✖️ | / | ✔️ | |
TIMESTAMP | ✖️ | ✖️ | ✖️ | ✔️ | / | |
Rules for implicit type conversion in comparisons
DuckDB-based analytical instances have stricter and more consistent rules for type conversion and comparison. However, this behavior may differ from that of MySQL in some scenarios:
Implicit conversion from string to date: When a string is implicitly converted to a date, if the string format cannot be correctly parsed into a valid date value, the SQL query fails and reports an error.
Comparison rules between integer types: When different integer types are compared, DuckDB-based analytical instances convert them to the integer type with the larger value range.
Type conversion order for multiple-operand expressions: For multiple-operand expressions such as
col1 in (col2, col3, col4, ...), col1 between col2 and col3, coalesce(col1, col2, col3, ...), type conversion is performed in sequence.Compatibility difference for the YEAR type: In DuckDB-based analytical instances, the YEAR type is converted to the INTEGER type for comparison, which may cause incompatibility with MySQL. Example:
CREATE TABLE t1 (id YEAR PRIMARY KEY); INSERT INTO t1 VALUES (1980); SELECT * FROM t1 WHERE id BETWEEN 70 AND 90; # MySQL query result +------+ | id | +------+ | 1980 | +------+ # DuckDB-based analytical instance query result Empty set.String conversion rules for the Boolean type: DuckDB-based analytical instances support the conversion of six strings (
'1','0','yes','no','true', and'false') to the BOOLEAN type. An attempt to convert any other string results in an error. MySQL converts'1'totrueand all other strings tofalse. Therefore, the following SQL statement may return inconsistent results:CREATE TABLE t1 (id INT PRIMARY KEY); INSERT INTO t1 VALUES (1); SELECT id FROM t1 WHERE 'true'; # MySQL query result Empty set # DuckDB-based analytical instance query result +------+ | id | +------+ | 1 | +------+
When data of different types is compared, the system converts the data to a common type for comparison based on the rules in the following tables. If a comparison between types is not supported (✖️), an error is reported.
Regular string types refer to the following MySQL data types:
CHAR,VARCHAR,TINYTEXT,TEXT,MEDIUMTEXT,LONGTEXT,JSON,SET, andENUM.Binary string types refer to the following MySQL data types:
BINARY,VARBINARY,BIT,TINYBLOB,BLOB,MEDIUMBLOB, andLONGBLOB.
Comparison with basic scalar types
Source type | Comparison with basic scalar types | ||
String literal | Numeric literal | ||
Basic scalar | String literal | String | Numeric literal |
Numeric literal | Numeric literal | Larger-range numeric type | |
Value | BOOLEAN | BOOLEAN | Larger-range numeric type |
Integer types | Integer types | Larger-range numeric type | |
FLOAT | FLOAT | Larger-range numeric type | |
DOUBLE | DOUBLE | Larger-range numeric type | |
DECIMAL | DECIMAL | Larger-range numeric type | |
String | Regular string | Regular string | Numeric literal |
Binary string | Binary string | ✖️ | |
Date and time | YEAR | YEAR | Larger-range numeric type |
DATE | DATETIME | ✖️ | |
TIME | TIME | ✖️ | |
DATETIME | DATETIME | ✖️ | |
TIMESTAMP | TIMESTAMP | ✖️ | |
Comparison with numeric types
Source type | Comparison with numeric types | |||||
BOOLEAN | Integer types | FLOAT | DOUBLE | DECIMAL | ||
Basic scalar | String literal | BOOLEAN | Integer types | FLOAT | DOUBLE | DECIMAL |
Numeric literal | Larger-range numeric type | Larger-range numeric type | Larger-range numeric type | Larger-range numeric type | Larger-range numeric type | |
Numeric | BOOLEAN | BOOLEAN | Integer types | FLOAT (inequality comparison ✖️) | DOUBLE (inequality comparison ✖️) | DECIMAL (inequality comparison ✖️) |
Integer types | Integer types | Integer types | FLOAT | DOUBLE | DECIMAL | |
FLOAT | FLOAT (inequality comparison ✖️) | FLOAT | FLOAT | DOUBLE | FLOAT | |
DOUBLE | DOUBLE (inequality comparison ✖️) | DOUBLE | DOUBLE | DOUBLE | DOUBLE | |
DECIMAL | DECIMAL (inequality comparison ✖️) | DECIMAL | FLOAT | DOUBLE | DECIMAL | |
String | Regular string | BOOLEAN | Integer types | FLOAT | DOUBLE | DECIMAL |
Binary string | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ | |
Date and time | YEAR | INTEGER | Larger-range integer type | FLOAT | DOUBLE | DECIMAL |
DATE | ✖️ | ✖️ | ✖️ | DOUBLE | ✖️ | |
TIME | ✖️ | ✖️ | ✖️ | DOUBLE | ✖️ | |
DATETIME | ✖️ | ✖️ | ✖️ | DOUBLE | ✖️ | |
TIMESTAMP | ✖️ | ✖️ | ✖️ | DOUBLE | ✖️ | |
Comparison with string types
Source type | Comparison with string types | ||
Regular string | Binary string | ||
Basic scalar | String literal | Regular string | Binary string |
Numeric literal | Numeric literal | ✖️ | |
Numeric | BOOLEAN | BOOLEAN | ✖️ |
Integer types | Integer types | ✖️ | |
FLOAT | FLOAT | ✖️ | |
DOUBLE | DOUBLE | ✖️ | |
DECIMAL | DECIMAL | ✖️ | |
String | Regular string | Regular string | Binary string |
Binary string | Binary string | Binary string | |
Date and time | YEAR | INTEGER | ✖️ |
DATE | DATE | ✖️ | |
TIME | TIME | ✖️ | |
DATETIME | DATETIME | ✖️ | |
TIMESTAMP | TIMESTAMP | ✖️ | |
Comparison with date and time types
Source type | Comparison with date and time types | |||||
YEAR | DATE | TIME | DATETIME | TIMESTAMP | ||
Basic scalar | String literal | YEAR | DATETIME | TIME | DATETIME | TIMESTAMP |
Numeric literal | Larger-range numeric type | ✖️ | ✖️ | ✖️ | ✖️ | |
Numeric | BOOLEAN | INTEGER | ✖️ | ✖️ | ✖️ | ✖️ |
Integer types | Larger-range integer type | ✖️ | ✖️ | ✖️ | ✖️ | |
FLOAT | FLOAT | ✖️ | ✖️ | ✖️ | ✖️ | |
DOUBLE | DOUBLE | DOUBLE | DOUBLE | DOUBLE | DOUBLE | |
DECIMAL | DECIMAL | ✖️ | ✖️ | ✖️ | ✖️ | |
String | Regular string | INTEGER | DATE | TIME | DATETIME | TIMESTAMP |
Binary string | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ | |
Date and time | YEAR | INTEGER | ✖️ | ✖️ | ✖️ | ✖️ |
DATE | ✖️ | DATE | ✖️ | DATETIME | TIMESTAMP | |
TIME | ✖️ | ✖️ | TIME | ✖️ | ✖️ | |
DATETIME | ✖️ | DATETIME | ✖️ | DATETIME | DATETIME | |
TIMESTAMP | ✖️ | TIMESTAMP | ✖️ | DATETIME | TIMESTAMP | |
Potential inconsistencies in query results
Numeric operations
Comparisons of floating-point numbers may be incompatible. Example:
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 query result +------+ | id | +------+ | 1.23 | | 1.24 | +------+ # DuckDB-based analytical instance query result +------+ | id | +------+ | 1.24 | +------+The results of complex operations on floating-point numbers may be inconsistent due to floating-point errors.
When an operation is performed between integer and DECIMAL types, the result must not exceed the value range of the type. Otherwise, an overflow error may cause the execution to fail.
CREATE TABLE t1 (id TINYINT PRIMARY KEY); INSERT INTO t1 VALUES (100); SELECT id * 2 FROM t1; # MySQL query result +--------+ | id * 2 | +--------+ | 200 | +--------+ # DuckDB-based analytical instance query result ERROR 7577 (HY000): [DuckDB] Out of Range Error: Overflow in multiplication of INT8 (100 * 2)!.
Inconsistent results caused by collation rules
utf8mb4_0900_xx series collations are incompatible when comparing certain symbol characters. For example:
CREATE TABLE t1 ( id varchar(20) COLLATE utf8mb4_0900_ai_ci PRIMARY KEY );
INSERT INTO t1 VALUES ('!'), ('_');
SELECT * FROM t1 ORDER BY id;
# MySQL query result
+----+
| id |
+----+
| _ |
| ! |
+----+
# DuckDB-based analytical instance query result
+----+
| id |
+----+
| ! |
| _ |
+----+Handling of NULL values in vector subqueries with IN
In DuckDB-based analytical instances, the handling of NULL values in vector subqueries with IN may be incompatible with MySQL. Example:
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 query result
+-----------------------------------------+
| (id, col1) in (select id, col1 from t2) |
+-----------------------------------------+
| NULL |
| 0 |
+-----------------------------------------+
# DuckDB-based analytical instance query result
+-----------------------------------------+
| (id, col1) in (select id, col1 from t2) |
+-----------------------------------------+
| NULL |
| NULL |
+-----------------------------------------+For the data (2, 2), no matching item for the vector prefix exists in the IN clause. In this case, MySQL returns 0, whereas the DuckDB-based analytical instance returns NULL.
Limits on functions
The following table lists only the functions where DuckDB-based analytical instances differ from MySQL.
Aggregate functions
Function name | Supported | Limits |
| Yes | String, DECIMAL, and date types are not supported. |
| Yes | String, DECIMAL, and date types are not supported. |
| Yes | String, DECIMAL, and date types are not supported. |
| No | / |
Numeric functions
Numeric functions do not support the BOOLEAN type.
Function name | Supported | Limits |
| No | / |
| No | / |
| No | / |
String functions
MySQL DuckDB strictly distinguishes between binary strings (such as BLOB and VARBINARY) and strings (such as VARCHAR, TEXT, and JSON). Therefore, the following usage limits for string functions apply only to string inputs, not binary string inputs. Some functions that can accept binary strings as input include the following: CONCAT(), CONCAT_WS(), LENGTH(), MID(), OCTET_LENGTH(), REPEAT(), and TO_BASE64(). Unless otherwise specified, these functions have no usage restrictions.
Function name | Supported | Limits |
| Yes | In MySQL, |
| No | / |
| No | / |
| No | / |
| Yes | The first parameter of this function must be of the string type. A non-string type may produce results that are inconsistent with MySQL. |
| No | / |
| Yes | This function reports an error if base64 decoding fails. |
| Yes |
|
| No | / |
| No | / |
| No | / |
| Yes |
|
| Yes | In MySQL, |
| No | / |
| No | / |
| No | / |
| Yes | An error is reported if the function encounters a non-hexadecimal digit. |
| No | / |
Date functions
Function name | Supported | Limits |
| Yes | If the return value exceeds the value range of time-type data for the DuckDB-based analytical instance, inconsistent results will occur. |
| Yes |
|
| No | / |
| Yes | Years greater than 9999 are not supported. |
| Yes | Years greater than 9999 are not supported. |
| Yes | If the return value exceeds the value range of the time data type for the DuckDB-based analytical instance, inconsistent results may occur. |
| Yes |
|
| Yes | If the return value is outside the value range of the time-type data for a DuckDB-based analytical instance, inconsistent results may occur. |
| Yes | The DAY TIME format is not supported. For example: |
| No | / |
JSON functions
Function name | Supported? | Limits |
| No | / |
| No | / |
| No | / |
| No | / |
| Yes | The field order in the merged JSON object may be different from that in MySQL. |
| No | / |
| No | / |
| No | / |
| No | / |
| No | / |
| No | / |
| No | / |
| No | / |
| No | / |
| No | / |
| No | / |
Window functions
Function name | Supported | Limits |
| No | / |
| No | / |