TiDB函数和操作符
函数和操作符概述
TiDB 中函数和操作符使用方法与 MySQL 基本一致,详情参见: Functions and Operators。
在 SQL 语句中,表达式可用于诸如 SELECT
语句的 ORDER BY
或 HAVING
子句,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_APPENDJSON_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
表达式需至少满足以下条件之一,否则 DISTINCT
和 ORDER 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). 其中参数值意义及其范围如下:
- M 表示最大的数字位数 (精度). 1<= M <= 65.
- 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 中,以禁止特定表达式下推。
加入黑名单
执行以下步骤,可将一个或多个函数或运算符加入黑名单:
- 向 mysql.expr_pushdown_blacklist 插入对应的函数名或运算符名。
- 执行 admin reload expr_pushdown_blacklist;。
移出黑名单
执行以下步骤,可将一个或多个函数及运算符移出黑名单:
- 从 mysql.expr_pushdown_blacklist 表中删除对应的函数名或运算符名。
- 执行 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函数和操作符相关推荐
- PostgreSQL 10.1 手册_部分 II. SQL 语言_第 9 章 函数和操作符_9.15. JSON 函数和操作符...
9.15. JSON 函数和操作符 表 9.43展示了可以用于两种 JSON 数据类型(见第 8.14 节)的操作符. 表 9.43. json和jsonb 操作符 操作符 右操作数类型 描述 例子 ...
- PostgreSQL学习手册(五) 函数和操作符
PostgreSQL学习手册(五) 函数和操作符 一.逻辑操作符: 常用的逻辑操作符有:AND.OR和NOT.其语义与其它编程语言中的逻辑操作符完全相同. 二.比较操作符: 下面是Po ...
- MySQL函数和操作符(超详细,备着查找)
一.操作符 1.1 操作符优先级 以下列表显示了操作符优先级的由低到高的顺序.排列在同一行的操作符具有相同的优先级. 操作符 优先级 := 1 ||, OR, XOR 2 &&, AN ...
- PostgreSQL MySQL 兼容性之 - bit 函数和操作符
bit 函数和操作符 MySQL &Bitwise AND <<Left shift >>Shift right BIT_COUNTReturns the number ...
- PostgreSQL 10.1 手册_部分 II. SQL 语言_第 9 章 函数和操作符_9.18. 数组函数和操作符...
9.18. 数组函数和操作符 表 9.48显示了可以用于数组类型的操作符. 表 9.48. 数组操作符 操作符 描述 例子 结果 = 等于 ARRAY[1.1,2.1,3.1]::int[] = AR ...
- PostgreSQL学习笔记7之函数和操作符三
九.序列操作函数: 序列对象(也叫序列生成器)都是用CREATE SEQUENCE创建的特殊的单行表.一个序列对象通常用于为行或者表生成唯一的标识符.下面序列函数,为我们从序列对象中获取最新的序列值提 ...
- PostgreSQL学习笔记6之函数和操作符二
六.模式匹配: PostgreSQL中提供了三种实现模式匹配的方法:SQL LIKE操作符,更近一些的SIMILAR TO操作符,和POSIX-风格正则表达式. 1. LIKE: st ...
- PostgreSQL学习笔记5之函数和操作符一
一.逻辑操作符: 常用的逻辑操作符有:AND.OR和NOT.其语义与其它编程语言中的逻辑操作符完全相同. 二.比较操作符: 下面是PostgreSQL中提供的比较操作符列表: 操作符 描述 < ...
- postgresql常用函数及操作符及类型转换
为什么80%的码农都做不了架构师?>>> 一.逻辑操作符: 常用的逻辑操作符有:AND.OR和NOT.其语义与其它编程语言中的逻辑操作符完全相同. 二.比较操作符: 下面是Po ...
最新文章
- 用 Python 写 3D 游戏,太赞了
- python singleton design pattern super() 多继承
- __doPostBack简单的使用方法
- softmax函数与交叉熵损失函数
- 卡耐基梅隆计算机学院,卡内基梅隆计算机学院--计算机系简介
- SVM支持向量机,我用到的自学材料
- bzoj 2115: [Wc2011] Xor(DFS+线性基)
- IE设置自动获得代理(ISA20042006中设置相应项)
- jupyter in vscode python语法不高亮 单元格语言格式CVE
- unity 安装遇到问题
- 使用电脑群控制手机时,电脑硬件配置如何配?
- 详解Java 堆排序
- ERP-非财务人员的财务培训教(一.二)------财务基础知识
- 重启计算机后回收站,电脑回收站文件被清空了该如何恢复
- Go语言开发工具和插件
- 【C语言】指针基础知识点汇总
- 《雨巷》-- 戴望舒
- mysql简化的审批流程表设计
- 弃用消息队列!新一代消息系统已成气候!
- matlab norm函数使用_matlab中norm函数的用法