函数和操作符概述

TiDB 中函数和操作符使用方法与 MySQL 基本一致,详情参见: Functions and Operators。

在 SQL 语句中,表达式可用于诸如 SELECT 语句的 ORDER BYHAVING 子句,SELECT/DELETE/UPDATE 语句的 WHERE子句,或 SET 语句之类的地方。

可使用字面值,列名,NULL,内置函数,操作符等来书写表达式。其中有些表达式下推到 TiKV 上执行,详见下推到 TiKV 的表达式列表。

表达式求值的类型转换

TiDB 中表达式求值的类型转换与 MySQL 基本一致,详情参见 MySQL 表达式求值的类型转换。

操作符

操作符 功能描述
AND, && 逻辑与
= 赋值 (可用于 SET 语句中, 或用于 UPDATE 语句的 SET 中 )
:= 赋值
BETWEEN … AND … 判断值满足范围
BINARY 将一个字符串转换为一个二进制字符串
& 位与
~ 位非
\| 位或
^ 按位异或
CASE case 操作符
DIV 整数除
/ 除法
= 相等比较
<=> 空值安全型相等比较
> 大于
>= 大于或等于
IS 判断一个值是否等于一个布尔值
IS NOT 判断一个值是否不等于一个布尔值
IS NOT NULL 非空判断
IS NULL 空值判断
<< 左移
< 小于
<= 小于或等于
LIKE 简单模式匹配
-
%, MOD 求余
NOT, ! 取反
NOT BETWEEN … AND … 判断值是否不在范围内
!=, <> 不等于
NOT LIKE 不符合简单模式匹配
NOT REGEXP 不符合正则表达式模式匹配
||, OR 逻辑或
+
REGEXP 使用正则表达式进行模式匹配
>> 右移
RLIKE REGEXP 同义词
*
- 取反符号
XOR 逻辑亦或

操作符优先级

操作符优先级显示在以下列表中,从最高优先级到最低优先级。同一行显示的操作符具有相同的优先级。

INTERVAL
BINARY
!
- (unary minus), ~ (unary bit inversion)
^
*, /, DIV, %, MOD
-, +
<<, >>
&
|
= (comparison), <=>, >=, >, <=, <, <>, !=, IS, LIKE, REGEXP, IN
BETWEEN, CASE, WHEN, THEN, ELSE
NOT
AND, &&
XOR
OR, ||
= (assignment), :=

详情参见 这里.

比较方法和操作符

操作符名 功能描述
BETWEEN … AND … 判断值是否在范围内
COALESCE() 返回第一个非空值
= 相等比较
<=> 空值安全型相等比较
> 大于
>= 大于或等于
GREATEST() 返回最大值
IN() 判断值是否在一个值的集合内
INTERVAL() 返回一个小于第一个参数的参数的下标
IS 判断是否等于一个布尔值
IS NOT 判断是否不等于一个布尔值
IS NOT NULL 非空判断
IS NULL 空值判断
ISNULL() 判断参数是否为空
LEAST() 返回最小值
< 小于
<= 小于或等于
LIKE 简单模式匹配
NOT BETWEEN … AND … 判断值是否不在范围内
!=, <> 不等于
NOT IN() 判断值是否不在一个值的集合内
NOT LIKE 不满足简单模式匹配
STRCMP() 比较两个字符串

详情参见 这里.

逻辑操作符

操作符名 功能描述
AND, && 逻辑与
NOT, ! 逻辑非
\|\|, OR 逻辑或
XOR 逻辑亦或

详情参见 这里.

赋值操作符

操作符名 功能描述
= 赋值(可用于SET语句中,或用于UPDATE语句的SET中)
:= 赋值

详情参见 这里.

控制流程函数

TiDB 支持使用 MySQL 5.7 中提供的所有控制流程函数。

函数名 功能描述
CASS Case操作符
IF() 构建if/else
IFNULL() 构建NUll if/else
NULLIF() 如果expr1 = expr2,返回NULL

字符串函数

TiDB 支持使用 MySQL 5.7 中提供的大部分字符串函数。

支持的函数

函数名 功能描述
ASCII() 返回最左字符的数值
BIN() 返回一个数的二进制值的字符串表示
BIT_LENGTH() 返回字符串的位长度
CHAR() 返回由整数的代码值所给出的字符组成的字符串
CHAR_LENGTH() 返回字符串的字符长度
CHARACTER_LENGTH() 与 CHAR_LENGTH() 功能相同
CONCAT() 返回连接的字符串
CONCAT_WS() 返回由分隔符连接的字符串
ELT() 返回指定位置的字符串
EXPORT_SET() 返回一个字符串,其中值位中设置的每个位,可以得到一个 on 字符串,而每个未设置的位,可以得到一个 off 字符串
FIELD() 返回参数在后续参数中出现的第一个位置
FIND_IN_SET() 返回第一个参数在第二个参数中出现的位置
FORMAT() 返回指定小数位数格式的数字
FROM_BASE64() 解码 base-64 表示的字符串,并返回结果
HEX() 返回一个十进制数或字符串值的 16 进制表示
INSERT() 在指定位置插入一个子字符串,最多不超过指定字符数
INSTR() 返回第一次出现的子字符串的索引
LCASE() 与 LOWER() 功能相同
LEFT() 返回最左侧指定长度的字符
LENGTH() 返回字符串长度,单位为字节
LIKE 进行简单模式匹配
LOCATE() 返回第一次出现的子字符串的位置
LOWER() 返回全小写的参数
LPAD() 返回字符串参数,左侧添加指定字符串
LTRIM() 去掉前缀空格
MAKE_SET() 返回一组用逗号分隔的字符串,这些字符串的位数与给定的 bits 参数对应
MID() 返回一个以指定位置开始的子字符串
NOT LIKE 否定简单模式匹配
NOT REGEXP REGEXP 的否定形式
OCT() 返回一个数值的八进制表示,形式为字符串
OCTET_LENGTH() 与 LENGTH() 功能相同
ORD() 返回该参数最左侧字符的字符编码
POSITION() 与 LOCATE() 功能相同
QUOTE() 使参数逃逸,为了在 SQL 语句中使用
REGEXP 使用正则表达式匹配模式
REPEAT() 以指定次数重复一个字符串
REPLACE() 替换所有出现的指定字符串
REVERSE() 反转字符串里的所有字符
RIGHT() 返回指定数量的最右侧的字符
RLIKE 与 REGEXP 功能相同
RPAD() 以指定次数添加字符串
RTRIM() 去掉后缀空格
SPACE() 返回指定数量的空格,形式为字符串
STRCMP() 比较两个字符串
SUBSTR() 返回指定的子字符串
SUBSTRING() 返回指定的子字符串
SUBSTRING_INDEX() 从一个字符串中返回指定出现次数的定界符之前的子字符串
TO_BASE64() 返回转化为 base-64 表示的字符串参数
TRIM() 去掉前缀和后缀空格
UCASE() 与 UPPER() 功能相同
UNHEX() 返回一个数的十六进制表示,形式为字符串
UPPER() 参数转换为大写形式

不支持的函数

  • LOAD_FILE()
  • MATCH
  • SOUNDEX()
  • SOUNDS LIKE
  • WEIGHT_STRING()

数值函数与操作符

TiDB 支持使用 MySQL 5.7 中提供的所有数值函数与操作符。

算术操作符

操作符名 功能描述
+ 加号
- 减号
* 乘号
/ 除号
DIV 整数除法
%, MOD 模运算,取余
- 更改参数符号

数学函数

函数名 功能描述
POW() 返回参数的指定乘方的结果值
POWER() 返回参数的指定乘方的结果值
EXP() 返回 e(自然对数的底)的指定乘方后的值
SQRT() 返回非负数的二次方根
LN() 返回参数的自然对数
LOG() 返回第一个参数的自然对数
LOG2() 返回参数以 2 为底的对数
LOG10() 返回参数以 10 为底的对数
PI() 返回 pi 的值
TAN() 返回参数的正切值
COT() 返回参数的余切值
SIN() 返回参数的正弦值
COS() 返回参数的余弦值
ATAN() 返回参数的反正切值
ATAN2(), ATAN() 返回两个参数的反正切值
ASIN() 返回参数的反正弦值
ACOS() 返回参数的反余弦值
RADIANS() 返回由度转化为弧度的参数
DEGREES() 返回由弧度转化为度的参数
MOD() 返回余数
ABS() 返回参数的绝对值
CEIL() 返回不小于参数的最小整数值
CEILING() 返回不小于参数的最小整数值
FLOOR() 返回不大于参数的最大整数值
ROUND() 返回参数最近似的整数或指定小数位数的数值
RAND() 返回一个随机浮点值
SIGN() 返回参数的符号
CONV() 不同数基间转换数字,返回数字的字符串表示
TRUNCATE() 返回被舍位至指定小数位数的数字
CRC32() 计算循环冗余码校验值并返回一个 32 位无符号值

日期和时间函数

函数名 功能描述
ADDDATE() 将时间间隔添加到日期上
ADDTIME() 时间数值相加
CONVERT_TZ() 转换时区
CURDATE() 返回当前日期
CURRENT_DATE(), CURRENT_DATE 与 CURDATE() 同义
CURRENT_TIME(), CURRENT_TIME 与 CURTIME() 同义
CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP 与 NOW() 同义
CURTIME() 返回当前时间
DATE() 从日期或日期/时间表达式中提取日期部分
DATE_ADD() 将时间间隔添加到日期上
DATE_FORMAT() 返回满足指定格式的日期/时间
DATE_SUB() 从日期减去指定的时间间隔
DATEDIFF() 返回两个日期间隔的天数
DAY() 与 DAYOFMONTH() 同义
DAYNAME() 返回星期名称
DAYOFMONTH() 返回参数对应的天数部分(1-31)
DAYOFWEEK() 返回参数对应的星期下标
DAYOFYEAR() 返回参数代表一年的哪一天 (1-366)
EXTRACT() 提取日期/时间中的单独部分
FROM_DAYS() 将天数转化为日期
FROM_UNIXTIME() 将 Unix 时间戳格式化为日期
GET_FORMAT() 返回满足日期格式的字符串
HOUR() 提取日期/时间表达式中的小时部分
LAST_DAY 返回参数中月份的最后一天
LOCALTIME(), LOCALTIME 与 NOW() 同义
LOCALTIMESTAMP, LOCALTIMESTAMP() 与 NOW() 同义
MAKEDATE() 根据给定的年份和一年中的天数生成一个日期
MAKETIME() 根据给定的时、分、秒生成一个时间
MICROSECOND() 返回参数的微秒部分
MINUTE() 返回参数的分钟部分
MONTH() 返回参数的月份部分
MONTHNAME() 返回参数的月份名称
NOW() 返回当前日期和时间
PERIOD_ADD() 在年-月表达式上添加一段时间(数个月)
PERIOD_DIFF() 返回间隔的月数
QUARTER() 返回参数对应的季度(1-4)
SEC_TO_TIME() 将秒数转化为 ‘HH:MM:SS’ 的格式
SECOND() 返回秒数(0-59)
STR_TO_DATE() 将字符串转化为日期
SUBDATE() 当传入三个参数时作为 DATE_SUB() 的同义
SUBTIME() 从一个时间中减去一段时间
SYSDATE() 返回该方法执行时的时间
TIME() 返回参数的时间表达式部分
TIME_FORMAT() 格式化时间
TIME_TO_SEC() 返回参数对应的秒数
TIMEDIFF() 返回时间间隔
TIMESTAMP() 传入一个参数时候,该方法返回日期或日期/时间表达式, 传入两个参数时候, 返回参数的和
TIMESTAMPADD() 在日期/时间表达式上增加一段时间间隔
TIMESTAMPDIFF() 从日期/时间表达式中减去一段时间间隔
TO_DAYS() 将参数转化对应的天数(从第 0 年开始)
TO_SECONDS() 将日期或日期/时间参数转化为秒数(从第 0 年开始)
UNIX_TIMESTAMP() 返回一个 Unix 时间戳
UTC_DATE() 返回当前的 UTC 日期
UTC_TIME() 返回当前的 UTC 时间
UTC_TIMESTAMP() 返回当前的 UTC 日期和时间
WEEK() 返回参数所在的一年中的星期数
WEEKDAY() 返回星期下标
WEEKOFYEAR() 返回参数在日历中对应的一年中的星期数
YEAR() 返回参数对应的年数
YEARWEEK() 返回年数和星期数

位函数和操作符

TiDB 支持使用 MySQL 5.7 中提供的所有位函数和操作符。

位函数和操作符表

函数和操作符名 功能描述
BIT_COUNT() 返回参数二进制表示中为 1 的个数
& 位与
~ 按位取反
| 位或
0 位亦或
<< 左移
>> 右移

Cast 函数和操作符

Cast 函数和操作符用于将某种数据类型的值转换为另一种数据类型。TiDB 支持使用 MySQL 5.7 中提供的所有 Cast 函数和操作符。

Cast 函数和操作符表

函数和操作符名 功能描述
BINARY 将一个字符串转换成一个二进制字符串
CAST() 将一个值转换成一个确定类型
CONVERT() 将一个值转换成一个确定类型

加密和压缩函数

TiDB 支持使用 MySQL 5.7 中提供的大部分加密和压缩函数。

支持的函数

函数名 功能描述
MD5()                                                             计算字符串的 MD5 校验和      
PASSWORD() 计算并返回密码字符串
RANDOM_BYTES() 返回随机字节向量
SHA1(), SHA()                                                   计算 SHA-1 160 位校验和              
SHA2()                                                           计算 SHA-2 校验和                      
AES_DECRYPT() 使用 AES 解密
AES_ENCRYPT() 使用 AES 加密
COMPRESS() 返回经过压缩的二进制字符串
UNCOMPRESS() 解压缩字符串
UNCOMPRESSED_LENGTH()                             返回字符串解压后的长度
CREATE_ASYMMETRIC_PRIV_KEY() 创建私钥
CREATE_ASYMMETRIC_PUB_KEY() 创建公钥
CREATE_DH_PARAMETERS() 创建 DH 共享密钥
CREATE_DIGEST() 从字符串创建摘要
ASYMMETRIC_DECRYPT() 使用公钥或私钥解密密文
ASYMMETRIC_DERIVE() 从非对称密钥导出对称密钥
ASYMMETRIC_ENCRYPT() 使用公钥或私钥加密明文
ASYMMETRIC_SIGN() 从摘要创建签名
ASYMMETRIC_VERIFY() 验证签名字符串是否匹配摘要字符串

不支持的函数

  • DES_DECRYPT()DES_ENCRYPT()OLD_PASSWORD()ENCRYPT():这些函数在 MySQL
    5.7 中被废弃,并且已在 MySQL 8.0 中移除。
  • VALIDATE_PASSWORD_STRENGTH() 函数。
  • 只在 MySQL 企业版中支持的函数。见 Issue #2632。

信息函数

TiDB 支持使用 MySQL 5.7 中提供的大部分信息函数。

支持的函数

函数名 功能描述
BENCHMARK() 循环执行一个表达式
CONNECTION_ID() 返回当前连接的连接 ID (线程 ID)
CURRENT_USER(), CURRENT_USER 返回当前用户的用户名和主机名
DATABASE() 返回默认(当前)的数据库名
FOUND_ROWS() 该函数返回对于一个包含 LIMIT 的 SELECT 查询语句,在不包含 LIMIT 的情况下回返回的记录数
LAST_INSERT_ID() 返回最后一条 INSERT 语句中自增列的值
ROW_COUNT() 影响的行数
SCHEMA() 与 DATABASE() 同义
SESSION_USER() 与 USER() 同义
SYSTEM_USER() 与 USER() 同义
USER() 返回客户端提供的用户名和主机名
VERSION() 返回当前 MySQL 服务器的版本信息
TIDB_VERSION() 返回当前 TiDB 服务器的版本信息

## 不支持的函数

  • CHARSET()
  • COERCIBILITY()
  • COLLATION()

JSON 函数及语法糖

TiDB 支持 MySQL 5.7 GA 版本发布的大多数 JSON 函数。MySQL 5.7 发布后,又增加了更多 JSON 函数,TiDB 并未支持所有这些函数(参见未支持的函数)。

创建 JSON 值的函数

函数及语法糖 功能描述
JSON_ARRAY([val[, val] …]) 根据一系列元素创建一个 JSON 文档
JSON_OBJECT(key, val[, key, val] …) 根据一系列 K/V 对创建一个 JSON 文档
JSON_QUOTE(string) 返回一个字符串,该字符串为带引号的 JSON 值

搜索 JSON 值的函数

函数及语法糖 功能描述
JSON_CONTAINS(target, candidate[, path]) 通过返回 1 或 0 来表示目标 JSON 文档中是否包含给定的 candidate JSON 文档
JSON_CONTAINS_PATH(json_doc, one_or_all, path[, path] …) 通过返回 0 或 1 来表示一个 JSON 文档在给定路径是否包含数据
JSON_EXTRACT(json_doc, path[, path] …) 从 JSON 文档中解出某一路径对应的子文档
-> 返回执行路径后面的 JSON 列的值;JSON_EXTRACT(doc, path_literal) 的语法糖
->> 返回执行路径后面的 JSON 列的值和转义后的结果; JSON_UNQUOTE(JSON_EXTRACT(doc, path_literal)) 的语法糖
JSON_KEYS(json_doc[, path]) 返回从 JSON 对象的顶级值作为 JSON array 的键,如果给定了路径参数,则从选定路径中获取顶级键

修改 JSON 值的函数

函数及语法糖 功能描述
JSON_INSERT(json_doc, path, val[, path, val] …) 在 JSON 文档中在某一路径下插入子文档
JSON_MERGE(json_doc, json_doc[, json_doc] …) 已废弃的 JSON_MERGE_PRESERVE 别名
JSON_MERGE_PRESERVE(json_doc, json_doc[, json_doc] …) 将两个或多个 JSON 文档合并成一个文档,并返回合并结果
JSON_REMOVE(json_doc, path[, path] …) 移除 JSON 文档中某一路径下的子文档
JSON_REPLACE(json_doc, path, val[, path, val] …) 替换 JSON 文档中的某一路径下的子文档
JSON_SET(json_doc, path, val[, path, val] …) 在 JSON 文档中为某一路径设置子文档
JSON_UNQUOTE(json_val) 去掉 JSON 值外面的引号,返回结果为字符串

返回 JSON 值属性的函数

函数及语法糖 功能描述
JSON_DEPTH(json_doc) 返回 JSON 文档的最大深度
JSON_LENGTH(json_doc[, path]) 返回 JSON 文档的长度;如果路径参数已定,则返回该路径下值的长度
JSON_TYPE(json_val) 检查某 JSON 文档内部内容的类型

未支持的函数

TiDB 暂未支持以下 JSON 函数。相关进展参见 TiDB #7546:

  • JSON_APPEND 及其别名 JSON_ARRAY_APPEND
  • JSON_ARRAY_INSERT
  • JSON_DEPTH
  • JSON_MERGE_PATCH
  • JSON_PRETTY
  • JSON_SEARCH
  • JSON_STORAGE_SIZE
  • JSON_VALID
  • JSON_ARRAYAGG
  • JSON_OBJECTAGG

GROUP BY 聚合函数

TiDB 支持的 MySQL GROUP BY 聚合函数如下所示:

函数名 功能描述
COUNT() 返回检索到的行的数目
COUNT(DISTINCT) 返回不同值的数目
SUM() 返回和
AVG() 返回平均值
MAX() 返回最大值
MIN() 返回最小值
GROUP_CONCAT() 返回连接的字符串

注意:

  • 除非另有说明,否则聚合函数默认忽略 NULL 值。
  • 如果在不包含 GROUP BY 子句的语句中使用聚合函数,则相当于对所有行进行分组。

GROUP BY 修饰符

TiDB 目前不支持 GROUP BY 修饰符,例如 WITH ROLLUP,将来会提供支持。详情参阅 #4250。

对 SQL 模式的支持

TiDB 支持 SQL 模式 ONLY_FULL_GROUP_BY,当启用该模式时,TiDB 拒绝不明确的非聚合列的查询。例如,以下查询在启用 ONLY_FULL_GROUP_BY 时是不合规的,因为 SELECT 列表中的非聚合列 “b” 在 GROUP BY 语句中不显示:

drop table if exists t;
create table t(a bigint, b bigint, c bigint);
insert into t values(1, 2, 3), (2, 2, 3), (3, 2, 3);
select a, b, sum(c) from t group by a;
+------+------+--------+
| a    | b    | sum(c) |
+------+------+--------+
|    1 |    2 |      3 |
|    2 |    2 |      3 |
|    3 |    2 |      3 |
+------+------+--------+
3 rows in set (0.01 sec)
set sql_mode = 'ONLY_FULL_GROUP_BY';
Query OK, 0 rows affected (0.00 sec)
select a, b, sum(c) from t group by a;
ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'b' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

目前,TiDB 默认开启 SQL 模式 ONLY_FULL_GROUP_BY。

与 MySQL 的区别

TiDB 目前实现的 ONLY_FULL_GROUP_BY 没有 MySQL 5.7 严格。例如,假设我们执行以下查询,希望结果按 “c” 排序:

drop table if exists t;
create table t(a bigint, b bigint, c bigint);
insert into t values(1, 2, 1), (1, 2, 2), (1, 3, 1), (1, 3, 2);
select distinct a, b from t order by c;

要对结果进行排序,必须先清除重复。但选择保留哪一行会影响 c 的保留值,也会影响排序,并使其具有任意性。

在 MySQL 中,ORDER BY 表达式需至少满足以下条件之一,否则 DISTINCTORDER BY 查询将因不合规而被拒绝:

  • 表达式等同于 SELECT 列表中的一个。
  • 表达式引用并属于查询选择表的所有列都是 SELECT 列表的元素。

但是在 TiDB 中,上述查询是合规的,详情参阅 #4254。

TiDB 中另一个标准 SQL 的扩展允许 HAVING 子句中的引用使用 SELECT 列表中的别名表达式。例如:以下查询返回在 orders 中只出现一次的 name 值:

select name, count(name) from orders
group by name
having count(name) = 1;

这个 TiDB 扩展允许在聚合列的 HAVING 子句中使用别名:

select name, count(name) as c from orders
group by name
having c = 1;

标准 SQL 只支持 GROUP BY 子句中的列表达式,以下语句不合规,因为 FLOOR(value/100) 是一个非列表达式:

select id, floor(value/100)
from tbl_name
group by id, floor(value/100);

TiDB 对标准 SQL 的扩展支持 GROUP BY 子句中非列表达式,认为上述语句合规。

标准 SQL 也不支持 GROUP BY 子句中使用别名。TiDB 对标准 SQL 的扩展支持使用别名,查询的另一种写法如下:

select id, floor(value/100) as val
from tbl_name
group by id, val;

TiDB 不支持的聚合函数

TiDB 目前不支持的聚合函数如下所示,相关进展参阅 TiDB #7623。

  • STD, STDDEV, STDDEV_POP
  • STDDEV_SAMP
  • VARIANCE, VAR_POP
  • VAR_SAMP
  • JSON_ARRAYAGG
  • JSON_OBJECTAGG

窗口函数

TiDB 中窗口函数的使用方法与 MySQL 8.0 基本一致,详情可参见 MySQL 窗口函数。由于窗口函数会使用一些保留关键字,可能导致原先可以正常执行的 SQL 语句在升级 TiDB 后无法被解析语法,此时可以将 tidb_enable_window_function 设置为 0,该参数的默认值为 1。
TiDB 支持的窗口函数如下所示:

函数名 功能描述
CUME_DIST() 返回一组值中的累积分布
DENSE_RANK() 返回分区中当前行的排名,并且排名是连续的
FIRST_VALUE() 当前窗口中第一行的表达式值
LAG() 分区中当前行前面第 N 行的表达式值
LAST_VALUE() 当前窗口中最后一行的表达式值
LEAD() 分区中当前行后面第 N 行的表达式值
NTH_VALUE() 当前窗口中第 N 行的表达式值
NTILE() 将分区划分为 N 桶,为分区中的每一行分配桶号
PERCENT_RANK() 返回分区中小于当前行的百分比
RANK() 返回分区中当前行的排名,排名可能不连续
ROW_NUMBER() 返回分区中当前行的编号

其他函数

TiDB 支持使用 MySQL 5.7 中提供的大部分其他函数。

支持的函数

函数名 功能描述
ANY_VALUE() ONLY_FULL_GROUP_BY 模式下,防止带有 GROUP BY 的语句报错
DEFAULT() 返回表的某一列的默认值
INET_ATON() 将 IP 地址转换为数值
INET_NTOA() 将数值转换为 IP 地址
INET6_ATON() 将 IPv6 地址转换为数值  
INET6_NTOA() 将数值转换为 IPv6 地址
IS_IPV4() 判断参数是否为 IPv4 地址
IS_IPV4_COMPAT() 判断参数是否为兼容 IPv4 的地址
IS_IPV4_MAPPED() 判断参数是否为 IPv4 映射的地址
IS_IPV6() 判断参数是否为 IPv6 地址
NAME_CONST() 可以用于重命名列名
SLEEP() 让语句暂停执行几秒时间
UUID() 返回一个通用唯一识别码 (UUID)
VALUES() 定义 INSERT 语句使用的值

不支持的函数

| GET_LOCK() | 获取命名锁,详见 TiDB #10929 | | RELEASE_LOCK() | 释放命名锁,详见 TiDB #10929 | | UUID_SHORT() | 基于特定假设提供唯一的 UUID,目前这些假设在 TiDB 中不存在,详见 TiDB #4620 | | MASTER_WAIT_POS() | 与 MySQL 同步相关 |

精度数学

TiDB 中精度数学计算与 MySQL 中基本一致, 详情请参见: Precision Math.

  • 数值类型
  • DECIMAL 数据类型的特性

数值类型

精确数值运算的范围包括精确值数据类型(整型和 DECIMAL 类型), 以及精确值数字字面量. 近似值数据类型和近似值数字字面量被作为浮点数来处理.

精确值数字字面量包含整数部分或小数部分, 或二者都包含. 精确值数字字面量可以包含符号位. 例如: 1, .2, 3.4, -5, -6.78, +9.10.

近似值数字字面量以一个包含尾数和指数的科学计数法表示(基数为 10). 其中尾数和指数可以分别或同时带有符号位. 例如: 1.2E3, 1.2E-3, -1.2E3, -1.2E-3.

两个看起来相似的数字可能会被以不同的方式进行处理. 例如, 2.34 是精确值(定点数), 而 2.3E0 是近似值(浮点数).

DECIMAL 数据类型是定点数类型, 其运算是精确计算. FLOAT 和 DOUBLE 数据类型是浮点类型, 其运算是近似计算.

DECIMAL 数据类型的特性

本节讨论 DECIMAL 数据类型的特性, 主要涉及以下几点:

  • 最大位数
  • 存储格式
  • 存储要求

DECIMAL 列的声明语法为 DECIMAL(M, D). 其中参数值意义及其范围如下:

  1. M 表示最大的数字位数 (精度). 1<= M <= 65.
  2. D 表示小数点右边数字的位数 (标度). 1 <= D <= 30 且 不大于 M.

M 的最大值 65 表示 DECIMAL 值的计算精确到 65 位数字. 该精度同样适用于其精确值字面量.

DECIMAL 列的值采用二进制进行存储, 其将每 9 位十进制数字包装成 4 个字节. 其中整数和小数部分分别确定所需的存储空间. 如果数字位数为 9 的倍数, 则每 9 位十进制数字各采用 4 个字节进行存储, 对于剩余不足 9 位的数字, 所需的存储空间如下表所示.

剩余数字位数 存储所需字节数
0 0
1–2 1
3–4 2
5–6 3
7–9 4

例如, 定义类型为 DECIMAL(18, 9) 的列, 其小数点两侧均各包含 9 位十进制数字, 因此, 分别需要 4 个字节的存储空间. 定义类型为 DECIMAL(20, 6) 的列, 其小数部分包含 6 位十进制数字, 整数部分包含 14 位十进制数字. 整数部分中 9 位数字需要 4 个字节进行存储, 其余 5 位数字需要 3 个字节进行存储. 小数部分 6 位数字需要 3 个字节进行存储.

DECIMAL 列不存储前导的字符 + 或字符 - 或数字 0. 如果将 +0003.1 插入到 DECIMAL(5, 1) 列中, 则将其存储为3.1. 对于负数, 不存储字符 - 的字面值.

DECIMAL 列不允许插入大于列定义的隐含范围的值. 例如, DECIMAL(3, 0) 列范围为 -999 到 999. DECIMAL(M, D) 列小数点左边部分最多支持 M-D 位数字.

有关 DECIMAL 值的内部格式完整说明, 请参阅 TiDB 源码文件 types/mydecimal.go.

表达式计算

在涉及精度数学计算的表达式中,TiDB 会尽可能不做任何修改的使用每个输入的数值。比如:在计算比较函数时,参与运算的数字将不做任何改变。在严格 SQL 模式下,向一个数据列插入一个值时,如果该值处于这一列的值域范围内,这个值将直接不做任何修改的直接插入进去,提取这个值的时候,取得的值和插入的值将会是同一个值。当处于非严格 SQL 模式时,TiDB 会允许数据插入过程中发生的数据截断。

处理数值类型表达式取决于这个表达式参数的具体值:

  • 当表达式参数中包含近似值时,这个表达式的结果也是近似值,TiDB 会使用浮点数对应的计算逻辑返回一个浮点数的结果
  • 当表达式参数中不包含任何近似值时(也就是说表达式的参数全部是精确值),如果某个精确值包含小数部分,TIDB 会对这个表达式使用
    DECIMAL 对应的计算逻辑,返回一个 DECIMAL 的结果,精确到 65 位数字
  • 其他情况下,表达式只会包含整数参数,这个表达式的结果也是精确的,TiDB 会使用整数对应的计算逻辑返回一个整数结果,精度和 BIGINT
    保持一致(64位)

如果数值类型表达式中包含字符串参数,这些字符串参数将被转换成双精度浮点数,这个表达式的计算结果将是个近似值。

向一个数值类型列插入数据的具体行为会受到 SQL 模式的影响。接下来的讨论将围绕严格模式以及 ERROR_FOR_DIVISION_BY_ZERO 模式展开,如果要打开所有的限制,可以简单的使用 TRADITIONAL 模式,这个模式将同时使用严格模式以及 ERROR_FOR_DIVISION_BY_ZERO 模式:

SET sql_mode = 'TRADITIONAL';

向一个具有精确值类型(DECIMAL 或者整数类型)的列插入数据时,如果插入的数据位于该列的值域范围内将使用该数据的精确值。如果该数据的小数部分太长,将会发生数值修约,这时会有 warning 产生,具体内容可以看”数值修约”。

如果该数据整数部分太长:

  • 如果没有开启严格模式,这个值会被截断并产生一个 warning
  • 如果开启了严格模式,将会产生一个数据溢出的 error

如果向一个数值类型列插入字符串,如果该字符串中包含非数值部分,TiDB 将这样做类型转换:

  • 在严格模式下,没有以数字开头的字符串(即使是一个空字符串)不能被被用作数字值并会返回一个 error 或者是 warning;
  • 以数字开头的字符串可以被转换,不过末尾的非数字部分会被截断。如果被截断的部分包含的不全是空格,在严格模式下这回产生一个 error 或者
    warning

默认情况下,如果计算的过程中发生了除数是 0 的现象将会得到一个 NULL 结果,并且不会有 warning 产生。通过设置适当的 SQL 模式,除以 0 的操作可以被限制:当设置 ERROR_FOR_DIVISION_BY_ZERO SQL 模式时,TiDB 的行为是:

  • 如果设置了严格 SQL 模式,INSERT 和 UPDATE 的过程中如果发生了除以 0 的操作,正在进行的 INSERT 或者
    UPDATE 操作会被禁止,并且会返回一个 error
  • 如果没有设置严格 SQL 模式,除以 0 的操作仅会返回一个 warning

假设我们有如下的 SQL 语句:

INSERT INTO t SET i = 1/0;

不同的 SQL 模式将会导致不同的结果如下:

sql_mode 的值 结果
没有 warning,没有 error,i 被设为 NULL
strict 没有 warning,没有 error,i 被设为 NULL
ERROR_FOR_DIVISION_BY_ZERO 有 warning,没有 error,i 被设为 NULL
strict, ERROR_FOR_DIVISION_BY_ZERO 有 error,插入失败

数值修约

round() 函数的结果取决于他的参数是否是精确值:

  • 如果参数是精确值,round() 函数将使用四舍五入的规则
  • 如果参数是一个近似值,round() 表达式的结果可能和 MySQL 不太一样
SELECT ROUND(2.5), ROUND(25E-1);
+------------+--------------+
| ROUND(2.5) | ROUND(25E-1) |
+------------+--------------+
|          3 |            3 |
+------------+--------------+
1 row in set (0.00 sec)

向一个 DECIMAL 或者整数类型列插入数据时,round 的规则将采用 round half away from zero 的方式:

CREATE TABLE t (d DECIMAL(10,0));
Query OK, 0 rows affected (0.01 sec)
INSERT INTO t VALUES(2.5),(2.5E0);
Query OK, 2 rows affected, 2 warnings (0.00 sec)
SELECT d FROM t;
+------+
| d    |
+------+
|    3 |
|    3 |
+------+
2 rows in set (0.00 sec)

下推到 TiKV 的表达式列表

当 TiDB 从 TiKV 中读取数据的时候,TiDB 会尽量下推一些表达式运算到 TiKV 中,从而减少数据传输量以及 TiDB 单一节点的计算压力。本文将介绍 TiDB 已支持下推的表达式,以及如何禁止下推特定表达式。

已支持下推的表达式列表

表达式分类 具体操作
逻辑运算 AND (&&), OR (||), NOT (!)
比较运算 <, <=, =, != (<>), >, >=, <=>, IN(), IS NULL, LIKE, IS TRUE, IS FALSE, COALESCE()
数值运算 +, -, *, /, ABS(), CEIL(), CEILING(), FLOOR()
控制流运算 CASE, IF(), IFNULL()
JSON运算 JSON_TYPE(json_val),
JSON_EXTRACT(json_doc, path[, path] …),
JSON_UNQUOTE(json_val),
JSON_OBJECT(key, val[, key, val] …),
JSON_ARRAY([val[, val] …]),
JSON_MERGE(json_doc, json_doc[, json_doc] …),
JSON_SET(json_doc, path, val[, path, val] …),
JSON_INSERT(json_doc, path, val[, path, val] …),
JSON_REPLACE(json_doc, path, val[, path, val] …),
JSON_REMOVE(json_doc, path[, path] …)
日期运算 DATE_FORMAT()

禁止特定表达式下推

当函数的计算过程由于下推而出现异常时,可通过黑名单功能禁止其下推来快速恢复业务。具体而言,你可以将上述支持的函数或运算符名加入黑名单 mysql.expr_pushdown_blacklist 中,以禁止特定表达式下推。

加入黑名单

执行以下步骤,可将一个或多个函数或运算符加入黑名单:

  1. 向 mysql.expr_pushdown_blacklist 插入对应的函数名或运算符名。
  2. 执行 admin reload expr_pushdown_blacklist;。

移出黑名单

执行以下步骤,可将一个或多个函数及运算符移出黑名单:

  1. 从 mysql.expr_pushdown_blacklist 表中删除对应的函数名或运算符名。
  2. 执行 admin reload expr_pushdown_blacklist;。

黑名单用法示例

以下示例首先将运算符 < 及 > 加入黑名单,然后将运算符 > 从黑名单中移出。

黑名单是否生效可以从 explain 结果中进行观察。

tidb> create table t(a int);
Query OK, 0 rows affected (0.01 sec)tidb> explain select * from t where a < 2 and a > 2;
+---------------------+----------+------+------------------------------------------------------------+
| id                  | count    | task | operator info                                              |
+---------------------+----------+------+------------------------------------------------------------+
| TableReader_7       | 0.00     | root | data:Selection_6                                           |
| └─Selection_6       | 0.00     | cop  | gt(test.t.a, 2), lt(test.t.a, 2)                           |
|   └─TableScan_5     | 10000.00 | cop  | table:t, range:[-inf,+inf], keep order:false, stats:pseudo |
+---------------------+----------+------+------------------------------------------------------------+
3 rows in set (0.00 sec)tidb> insert into mysql.expr_pushdown_blacklist values('<'), ('>');
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0tidb> admin reload expr_pushdown_blacklist;
Query OK, 0 rows affected (0.00 sec)tidb> explain select * from t where a < 2 and a > 2;
+---------------------+----------+------+------------------------------------------------------------+
| id                  | count    | task | operator info                                              |
+---------------------+----------+------+------------------------------------------------------------+
| Selection_5         | 8000.00  | root | gt(test.t.a, 2), lt(test.t.a, 2)                           |
| └─TableReader_7     | 10000.00 | root | data:TableScan_6                                           |
|   └─TableScan_6     | 10000.00 | cop  | table:t, range:[-inf,+inf], keep order:false, stats:pseudo |
+---------------------+----------+------+------------------------------------------------------------+
3 rows in set (0.00 sec)tidb> delete from mysql.expr_pushdown_blacklist where name = '>';
Query OK, 1 row affected (0.00 sec)tidb> admin reload expr_pushdown_blacklist;
Query OK, 0 rows affected (0.00 sec)tidb> explain select * from t where a < 2 and a > 2;
+-----------------------+----------+------+------------------------------------------------------------+
| id                    | count    | task | operator info                                              |
+-----------------------+----------+------+------------------------------------------------------------+
| Selection_5           | 2666.67  | root | lt(test.t.a, 2)                                            |
| └─TableReader_8       | 3333.33  | root | data:Selection_7                                           |
|   └─Selection_7       | 3333.33  | cop  | gt(test.t.a, 2)                                            |
|     └─TableScan_6     | 10000.00 | cop  | table:t, range:[-inf,+inf], keep order:false, stats:pseudo |
+-----------------------+----------+------+------------------------------------------------------------+
4 rows in set (0.00 sec)

注意:

  • admin reload expr_pushdown_blacklist 只对执行该 SQL 语句的 TiDB server
    生效。若需要集群中所有 TiDB server 生效,需要在每台 TiDB server 上执行该 SQL 语句。
  • 表达式黑名单功能在 v3.0.0 及以上版本中支持。
  • 在 v3.0.3 及以下版本中,不支持将某些运算符的原始名称文本(如 “>“、”+” 和 “is
    null”)加入黑名单中,部分运算符在黑名单中需使用别名。已支持下推的表达式中,别名与原始名不同的运算符见下表(不区分大小写)。
运算符原始名称 运算符别名
< LT
> GT
<= LE
>= GT
= EQ
!= NE
<> NE
<=> NullEQ
| bitor
&& bitand
|| or
! not
in IN
+ PLUS
- MINUS
* MUL
/ DIV
DIV INTDIV
IS NULL ISNULL
IS TRUE ISTRUE
IS FALSE ISFALSE

TiDB函数和操作符相关推荐

  1. PostgreSQL 10.1 手册_部分 II. SQL 语言_第 9 章 函数和操作符_9.15. JSON 函数和操作符...

    9.15. JSON 函数和操作符 表 9.43展示了可以用于两种 JSON 数据类型(见第 8.14 节)的操作符. 表 9.43. json和jsonb 操作符 操作符 右操作数类型 描述 例子 ...

  2. PostgreSQL学习手册(五) 函数和操作符

    PostgreSQL学习手册(五) 函数和操作符 一.逻辑操作符:     常用的逻辑操作符有:AND.OR和NOT.其语义与其它编程语言中的逻辑操作符完全相同. 二.比较操作符:     下面是Po ...

  3. MySQL函数和操作符(超详细,备着查找)

    一.操作符 1.1 操作符优先级 以下列表显示了操作符优先级的由低到高的顺序.排列在同一行的操作符具有相同的优先级. 操作符 优先级 := 1 ||, OR, XOR 2 &&, AN ...

  4. PostgreSQL MySQL 兼容性之 - bit 函数和操作符

    bit 函数和操作符 MySQL &Bitwise AND <<Left shift >>Shift right BIT_COUNTReturns the number ...

  5. PostgreSQL 10.1 手册_部分 II. SQL 语言_第 9 章 函数和操作符_9.18. 数组函数和操作符...

    9.18. 数组函数和操作符 表 9.48显示了可以用于数组类型的操作符. 表 9.48. 数组操作符 操作符 描述 例子 结果 = 等于 ARRAY[1.1,2.1,3.1]::int[] = AR ...

  6. PostgreSQL学习笔记7之函数和操作符三

    九.序列操作函数: 序列对象(也叫序列生成器)都是用CREATE SEQUENCE创建的特殊的单行表.一个序列对象通常用于为行或者表生成唯一的标识符.下面序列函数,为我们从序列对象中获取最新的序列值提 ...

  7. PostgreSQL学习笔记6之函数和操作符二

    六.模式匹配: PostgreSQL中提供了三种实现模式匹配的方法:SQL LIKE操作符,更近一些的SIMILAR TO操作符,和POSIX-风格正则表达式.     1. LIKE:     st ...

  8. PostgreSQL学习笔记5之函数和操作符一

    一.逻辑操作符: 常用的逻辑操作符有:AND.OR和NOT.其语义与其它编程语言中的逻辑操作符完全相同. 二.比较操作符: 下面是PostgreSQL中提供的比较操作符列表: 操作符 描述 < ...

  9. postgresql常用函数及操作符及类型转换

    为什么80%的码农都做不了架构师?>>>    一.逻辑操作符: 常用的逻辑操作符有:AND.OR和NOT.其语义与其它编程语言中的逻辑操作符完全相同. 二.比较操作符: 下面是Po ...

最新文章

  1. 用 Python 写 3D 游戏,太赞了
  2. python singleton design pattern super() 多继承
  3. __doPostBack简单的使用方法
  4. softmax函数与交叉熵损失函数
  5. 卡耐基梅隆计算机学院,卡内基梅隆计算机学院--计算机系简介
  6. SVM支持向量机,我用到的自学材料
  7. bzoj 2115: [Wc2011] Xor(DFS+线性基)
  8. IE设置自动获得代理(ISA20042006中设置相应项)
  9. jupyter in vscode python语法不高亮 单元格语言格式CVE
  10. unity 安装遇到问题
  11. 使用电脑群控制手机时,电脑硬件配置如何配?
  12. 详解Java 堆排序
  13. ERP-非财务人员的财务培训教(一.二)------财务基础知识
  14. 重启计算机后回收站,电脑回收站文件被清空了该如何恢复
  15. Go语言开发工具和插件
  16. 【C语言】指针基础知识点汇总
  17. 《雨巷》-- 戴望舒
  18. mysql简化的审批流程表设计
  19. 弃用消息队列!新一代消息系统已成气候!
  20. matlab norm函数使用_matlab中norm函数的用法

热门文章

  1. Django 图书-英雄
  2. python 输入一个数,判断是不是水仙花数
  3. iPhone SDK 包含哪些东西?
  4. cadence学习记录
  5. 真核生物 18S rRNA
  6. 未转变者服务器物品建筑id,未转变者建筑物id是什么 | 手游网游页游攻略大全...
  7. 设计模式——行为型模式之责任链模式(简简单单入门责任链,理解I/O流消息怎么逐步传递处理以及服务器框架转发)
  8. 基于C#winform的学生信息管理与成绩评价系统
  9. python初步学习(二) 3.19
  10. 转:各种文本格式转换的网站