操作符
GaussDB数据库兼容绝大多数MySQL的操作符,但存在部分差异。如未列出,操作符行为默认为GaussDB原生行为,目前存在MySQL不支持但是GaussDB支持的语句,在MySQL兼容性下,这类语句通常为系统内部使用,因此不建议使用。
操作符差异
- ORDER BY排序对NULL值处理的差异。MySQL在排序时会将NULL值排序在前面;GaussDB默认将NULL值默认排在最后面。GaussDB可以通过NULLS FIRST和NULLS LAST设置NULL值排序顺序。
- 有ORDER BY时,GaussDB输出顺序与MySQL一致。没有ORDER BY时,GaussDB不保证结果有序。
- 使用MySQL操作符时需要用括号表达式严格确保表达式的结合性,否则执行报错。例如:SELECT 1 regexp ('12345' regexp '123');。
- NULL值显示不同。MySQL会将NULL显示为“NULL”;GaussDB将NULL值显示为空值。
mysql> SELECT NULL; +------+ | NULL | +------+ | NULL | +------+ 1 row in set (0.00 sec)
GaussDB输出结果:m_db=# SELECT NULL; ?column? ---------- (1 row)
- 操作符执行后,列名显示不一致。MySQL会将NULL显示为“NULL”;GaussDB将NULL值显示为空值。
- 字符串转double遇到非法字符串时,告警信息不一致。MySQL在常量非法字符串报错,字段非法字符串不报错;GaussDB在常量非法字符串和字段非法字符串都报错。
- 比较操作符返回结果显示不同。MySQL返回1/0;GaussDB返回t/f。
MySQL数据库 |
GaussDB数据库 |
差异 |
---|---|---|
<> |
支持,存在差异 |
MySQL支持索引,GaussDB不支持索引。 |
<=> |
支持,存在差异 |
MySQL支持索引,GaussDB不支持索引、hash连接和合并连接。 |
行表达式 |
支持,存在差异 |
GaussDB: m_db=# SELECT (1,2) <=> row(2,3); ERROR: could not determine interpretation of row comparison operator <=> LINE 1: SELECT (1,2) <=> row(2,3); ^ HINT: unsupported operator. m_db=# SELECT (1,2) < NULL; ?column? ---------- (1 row) m_db=# SELECT (1,2) <> NULL; ?column? ---------- (1 row) m_db=# SELECT (1, 2) IS NULL; ?column? ---------- f (1 row) m_db=# SELECT ISNULL((1, 2)); ?column? ---------- f (1 row) m_db=# SELECT ROW(0,0) BETWEEN ROW(1,1) AND ROW(2,2); ERROR: un support type m_db=# SELECT ROW(NULL) AS x; x ---- () (1 row) MySQL: mysql> SELECT (1,2) <=> row(2,3); +--------------------+ | (1,2) <=> row(2,3) | +--------------------+ | 0 | +--------------------+ 1 row in set (0.00 sec) mysql> SELECT (1,2) < NULL; ERROR 1241 (21000): Operand should contain 2 column(s) mysql> SELECT (1,2) <> NULL; ERROR 1241 (21000): Operand should contain 2 column(s) mysql> SELECT (1, 2) IS NULL; ERROR 1241 (21000): Operand should contain 1 column(s) mysql> SELECT ISNULL((1, 2)); ERROR 1241 (21000): Operand should contain 1 column(s) mysql> SELECT NULL BETWEEN NULL AND ROW(2,2); ERROR 1241 (21000): Operand should contain 1 column(s) mysql> SELECT ROW(NULL) AS x; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') as x' at line 1 |
-- |
支持,存在差异 |
MySQL表示对一个操作数进行两次取反,结果等于原操作数;GaussDB表示注释。 |
!! |
支持,存在差异 |
MySQL:!!含义同!,表示取非。 GaussDB:!表示取非操作,当!与!中间存在空格时,表示连续两次取非(! !);当!与!中间没有空格时,表示阶乘(!!)。
说明:
|
[NOT] REGEXP |
支持,存在差异 |
|
LIKE |
支持,存在差异 |
MySQL:LIKE的左操作数只能是位运算或者算术运算或者由括号组成的表达式,LIKE的右操作数只能是单目运算符(不含NOT)或者括号组成的表达式。 GaussDB:LIKE的左右操作数可以是任意表达式。 |
[NOT] BETWEEN AND |
支持,存在差异 |
MySQL:[NOT] BETWEEN AND嵌套使用时从右到左结合。[NOT] BETWEEN AND的第1个操作数和第2个操作数只能是位运算或者算术运算或者由括号组成的表达式。 GaussDB:[NOT] BETWEEN AND嵌套使用时从左到右结合。[NOT] BETWEEN AND的第1个操作数和第2个操作数可以是任意表达式。 |
IN |
支持,存在差异 |
MySQL:IN的左操作数只能是位运算或者算术运算或者由括号组成的表达式。 GaussDB:IN的左操作数可以是任意表达式。不支持ROW IN (ROW,ROW....)形式的查询。 在开启精度传递的场景下,对表中的数据使用in操作符时,若表中数据为FLOAT类型、DOUBLE类型且包括相应精度和标度(如float(4,2),double(4,2)),GaussDB会根据精度和标度对值进行比较,MySQL会读取内存值(失真数值,导致比较不相等)。 --GaussDB: m_db=# CREATE TABLE test1(t_float float(4,2)); CREATE TABLE m_db=# INSERT INTO test1 VALUES(1.42),(2.42); INSERT 0 2 m_db=# SELECT t_float, t_float in (1.42,2.42) FROM test1; t_float | ?column? ---------+---------- 1.42 | t 2.42 | t (2 rows) --MySQL: mysql> CREATE TABLE test1(t_float float(4,2)); Query OK, 0 rows affected (0.01 sec) mysql> INSERT INTO test1 VALUES(1.42),(2.42); Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> SELECT t_float, t_float in (1.42,2.42) FROM test1; +---------+------------------------+ | t_float | t_float in (1.42,2.42) | +---------+------------------------+ | 1.42 | 0 | | 2.42 | 0 | +---------+------------------------+ 2 rows in set (0.00 sec) |
! |
支持,存在差异 |
MySQL:!的操作数只能是单目运算符(不含not)或者括号组成的表达式。 GaussDB:!的操作数可以是任意表达式。 |
# |
不支持 |
MySQL支持#注释,GaussDB不支持#注释。 |
BINARY |
支持,存在差异 |
GaussDB中支持的表达式和MySQL并不完全一致(包括一些函数、操作符等)。GaussDB独有的表达式“~”、“IS DISTINCT FROM”等,由于BINARY关键字优先级更高,使用BINARY expr会优先将BINARY与“~”、“IS DISTINCT FROM”的左参数合并,导致报错。 |
取负(-) |
支持,存在差异 |
取反结果类型和精度与MySQL不一致: CREATE TABLE t AS SELECT - -1;
在开启精度传递(m_format_behavior_compat_options = 'enable_precision_decimal')的情况下,负号加常量数据类型的精度可能与MySQL存在差异,MySQL 5.7中,当表达式中包含取反操作符时,结果精度中的最大长度(max_length)会根据表达式中取反操作符的数量增加,而GaussDB不会。例如:
|
/**/ |
不支持 |
GaussDB中语句中不支持/**/注释。 |
xor |
支持,存在差异 |
GaussDB的xor和MySQL的行为不同。GaussDB 优化器会有常数优化,会出现先计算表示结果是常数的情况。 GaussDB: m_db=# SELECT 1 xor null xor pow(200, 2000000) FROM dual; ERROR: value out of range: overflow m_db=# CREATE TABLE t1(a int, b int); CREATE TABLE m_db=# INSERT INTO t1 VALUES(2,2), (200, 2000000000); INSERT 0 2 m_db=# m_db=# m_db=# SELECT 1 xor null xor pow(a, b) FROM t1; ?column? ---------- (2 rows) MySQL: mysql> SELECT 1 xor null xor pow(200, 2000000) FROM dual; +----------------------------------+ | 1 xor null xor pow(200, 2000000) | +----------------------------------+ | NULL | +----------------------------------+ 1 row in set (0.00 sec) ysql> CREATE TABLE t1(a int, b int); Query OK, 0 rows affected (0.04 sec) mysql> INSERT INTO t1 VALUES(2,2), (200, 2000000000); Query OK, 2 rows affected (0.01 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> SELECT 1 xor null xor pow(a, b) FROM t1; +--------------------------+ | 1 xor null xor pow(a, b) | +--------------------------+ | NULL | | NULL | +--------------------------+ 2 rows in set (0.00 sec) |
IS NULL和IS NOT NULL |
支持,存在差异 |
MySQL的优先级小于逻辑运算符,GaussDB的优先级大于逻辑运算符。 |
XOR、|、&、<、>、<=、>=、=、!= |
支持,存在差异 |
MySQL执行机制为执行左操作数后,对结果进行判断是否为空,进而决定是否需要执行右操作数。 GaussDB执行机制是执行左右操作数后,对结果再进行判断是否为空。 当左操作数结果为空,右操作数执行报错时,MySQL不会报错直接返回,GaussDB会执行报错。 MySQL行为: mysql> SELECT version(); +------------------+ | version() | +------------------+ | 5.7.44-debug-log | +------------------+ 1 row in set (0.00 sec) mysql> DROP TABLE IF EXISTS data_type_table; Query OK, 0 rows affected (0.02 sec) mysql> CREATE TABLE data_type_table ( -> MyBool BOOL, -> MyBinary BINARY(10), -> MyYear YEAR -> ); Query OK, 0 rows affected (0.02 sec) mysql> INSERT INTO data_type_table VALUES (TRUE, 0x1234567890, '2021'); Query OK, 1 row affected (0.00 sec) mysql> SELECT (MyBool % MyBinary) | (MyBool - MyYear) FROM data_type_table; +-----------------------------------------+ | (MyBool % MyBinary) | (MyBool - MyYear) | +-----------------------------------------+ | NULL | +-----------------------------------------+ 1 row in set, 2 warnings (0.00 sec) GaussDB行为: m_db=# DROP TABLE IF EXISTS data_type_table; DROP TABLE m_db=# CREATE TABLE data_type_table ( m_db(# MyBool BOOL, m_db(# MyBinary BINARY(10), m_db(# MyYear YEAR m_db(# ); CREATE TABLE m_db=# INSERT INTO data_type_table VALUES (TRUE, 0x1234567890, '2021'); INSERT 0 1 m_db=# SELECT (MyBool % MyBinary) | (MyBool - MyYear) FROM data_type_table; WARNING: Truncated incorrect double value: '4Vx ' CONTEXT: referenced column: (MyBool % MyBinary) | (MyBool - MyYear) WARNING: division by zero CONTEXT: referenced column: (MyBool % MyBinary) | (MyBool - MyYear) ERROR: Bigint is out of range. CONTEXT: referenced column: (MyBool % MyBinary) | (MyBool - MyYear) |
+、-、*、 /、%、mod、div |
支持,存在差异 |
CREATE VIEW AS SELECT算数操作符('+', '-', '*', '/', '%', 'mod', 'div')内嵌b''常量时,MySQL 5.7返回类型可能存在unsigned标识,GaussDB不会。 MySQL输出结果: mysql> CREATE VIEW v22 as SELECT b'101' / b'101' c22; Query OK, 0 rows affected (0.00 sec) mysql> DESC v22; +-------+-----------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-----------------------+------+-----+---------+-------+ | c22 | decimal(5,4) unsigned | YES | | NULL | | +-------+-----------------------+------+-----+---------+-------+ 1 row in set (0.01 sec)
GaussDB输出结果:
m_db=# CREATE VIEW v22 AS SELECT b'101' / b'101' c22; CREATE VIEW m_db=# DESC v22; Field | Type | Null | Key | Default | Extra -------+--------------+------+-----+---------+------- c22 | decimal(5,4) | YES | | | (1 row) |
操作符组合示例 |
MySQL数据库 |
GaussDB数据库 |
说明 |
---|---|---|---|
SELECT 1 LIKE 3 & 1; |
不支持 |
支持 |
LIKE的右操作数不能是位运算符组成的表达式。 |
SELECT 1 LIKE 1 +1; |
不支持 |
支持 |
LIKE的右操作数不能是算术运算符组成的表达式。 |
SELECT 1 LIKE NOT 0; |
不支持 |
支持 |
LIKE的右操作数只能是+、-、!等单目操作符或者括号组成的表达式,NOT除外。 |
SELECT 1 BETWEEN 1 AND 2 BETWEEN 2 AND 3; |
从右到左结合 |
从左到右结合 |
建议加上括号明确运算的优先级,防止由于运算顺序的差异导致运算结果产生偏差。 |
SELECT 2 BETWEEN 1=1 AND 3; |
不支持 |
支持 |
BETWEEN的第2个操作数不能是比较操作符组成的表达式。 |
SELECT 0 LIKE 0 BETWEEN 1 AND 2; |
不支持 |
支持 |
BETWEEN的第1个操作数不能是模式匹配操作符组成的表达式。 |
SELECT 1 IN (1) BETWEEN 0 AND 3; |
不支持 |
支持 |
BETWEEN的第1个操作数不能是IN操作符组成的表达式。 |
SELECT 1 IN (1) IN (1); |
不支持 |
支持 |
第2个IN表达式左操作数不能是IN组成的表达式。 |
SELECT ! NOT 1; |
不支持 |
支持 |
!的操作数只能是+、-、!等单目操作符或者括号组成的表达式,NOT除外。 |
索引差异
- GaussDB当前仅支持UBTree和B-tree索引。
- 在执行LIKE模糊匹配,并通过EXPLAIN打印执行计划时,执行计划中会显示当前索引列对应字符序的最小/最大字符权重编码,该编码在不同的客户端字符集设置下的显示可能存在差异,但不影响LIKE模糊匹配查询结果的正确性。
- B-tree/UBTree索引场景保持原生GaussDB原有逻辑,即同一操作符族内的类型比较,支持索引扫描,其余索引类型暂未支持。
- 在使用GaussDB JDBC连接数据库时,GaussDB的YEAR类型在含有绑定参数的PBE场景下无法利用索引。
- WHERE子句中,索引字段类型和常量类型操作场景下,GaussDB中索引与MySQL索引支持存在差异,如表3所示。例如以下语句GaussDB不支持索引:
CREATE TABLE t(_int int); CREATE INDEX idx ON t(_int) USING BTREE; SELECT * FROM t WHERE _int > 2.0;
- WHERE子句里索引字段类型和常量类型操作场景中,可以使用cast函数将常数类型显式转换为字段类型,以便实现索引。
SELECT * FROM t WHERE _int > cast(2.0 AS signed);
- 在执行LIKE模糊匹配时,单字节字符集场景下,GaussDB创建前缀索引长度最长为2676字节(MySQL为3072字节),超过最大长度建议创建非前缀索引。
表3 索引支持差异 索引字段类型
常量类型
GaussDB是否支持
MySQL是否支持
整型
整型
是
是
浮点型
浮点型
是
是
定点型
定点型
是
是
字符串类型
字符串类型
是
是
二进制类型
二进制类型
是
是
带日期的时间类型
带日期的时间类型
是
是
TIME类型
TIME类型
是
是
带日期的时间类型
可转为带日期的时间类型(如20231130等整型)
是
是
带日期的时间类型
TIME类型
是
是
TIME类型
可转为TIME类型的常量(如203008等整型)
是
是
浮点型
整型
是
是
浮点型
定点型
是
是
浮点型
字符串类型
是
是
浮点型
二进制类型
是
是
浮点型
带日期的时间类型
是
是
浮点型
TIME类型
是
是
定点型
整型
是
是
字符串类型
带日期的时间类型
是
否
字符串类型
TIME类型
是
否
二进制类型
字符串类型
是
是
二进制类型
带日期的时间类型
是
否
二进制类型
TIME类型
是
否
整型
浮点型
否
是
整型
定点型
否
是
整型
字符串类型
否
是
整型
二进制类型
否
是
整型
带日期的时间类型
否
是
整型
TIME类型
否
是
定点型
浮点型
否
是
定点型
字符串类型
否
是
定点型
二进制类型
否
是
定点型
带日期的时间类型
否
是
定点型
TIME类型
否
是
字符串类型
二进制类型
否
是
带日期的时间类型
整型(不可转为带日期的时间类型)
否
是
带日期的时间类型
浮点型(不可转为带日期的时间类型)
否
是
带日期的时间类型
定点型(不可转为带日期的时间类型)
否
是
TIME类型
整型(不可转为TIME类型)
否
是
TIME类型
字符串类型(不可转为TIME类型)
否
是
TIME类型
二进制类型(不可转为TIME类型)
否
是
TIME类型
带日期的时间类型
否
是
YEAR类型
YEAR类型
是
是
YEAR类型
可转为YEAR类型的常量(如2034等整型)
是
是
BIT类型
BIT类型
否
是
SET/ENUM类型
字符串类型
否
是
SET/ENUM类型
整型
否
是
SET/ENUM类型
浮点型
否
是
SET/ENUM类型
时间类型
否
是
表4 是否支持走索引 索引字段类型
常量类型
GaussDB是否走索引
MySQL是否走索引
字符串类型
整型
否
否
字符串类型
浮点型
否
否
字符串类型
定点型
否
否
二进制类型
整型
否
否
二进制类型
浮点型
否
否
二进制类型
定点型
否
否
带日期的时间类型
字符串类型(不可转为带日期的时间类型)
否
否
带日期的时间类型
二进制类型(不可转为带日期的时间类型)
否
否
TIME类型
浮点型(不可转为TIME类型)
否
否
TIME类型
定点型(不可转为TIME类型)
否
否
BIT类型
字符串类型
否
否
- WHERE子句里索引字段类型和常量类型操作场景中,可以使用cast函数将常数类型显式转换为字段类型,以便实现索引。