第 19.1 节:算术运算符

MySQL 提供以下算术运算符:

运算符 名称 示例
+ 加法 SELECT 3+5; → 8
SELECT 3.5+2.5; → 6.0
SELECT 3.5+2; → 5.5
- 减法 SELECT 3-5; → -2
* 乘法 SELECT 3 * 5; → 15
/ 除法 SELECT 20 / 4; → 5
SELECT 355 / 113; → 3.1416
SELECT 10.0 / 0; → NULL
DIV 整数除法 SELECT 5 DIV 2; → 2
% 或 MOD 取模 SELECT 7 % 3; → 1
SELECT 15 MOD 4; → 3
SELECT 15 MOD -4; → 3
SELECT -15 MOD 4; → -3
SELECT -15 MOD -4; → -3
SELECT 3 MOD 2.5; → 0.5

BIGINT

如果算术运算中的所有数字都是整数,MySQL 使用 BIGINT(有符号 64 位)整数数据类型进行计算。例如:

SELECT (1024 * 1024 * 1024 * 1024 * 1024 * 1024) + 1;
-- 结果: 1152921504606846977

如果数字超出范围,可能会发生溢出。

DOUBLE

如果算术运算中有任何数字是小数,MySQL 使用 64 位 IEEE 754 浮点运算。使用浮点运算时要小心,因为许多浮点数本质上是近似值而非精确值。

第 19.2 节:数学常量

PI

返回 π 的值,格式化为 6 位小数。实际精度为 DOUBLE:

SELECT PI();   -- 3.141593

第 19.3 节:三角函数(SIN、COS 等)

角度以弧度为单位,而非度数。所有计算均使用 IEEE 754 64 位浮点数进行。所有浮点计算都会受到微小误差(称为机器 ε 误差)的影响,因此应避免试图比较它们的相等性。使用浮点数时无法避免这些误差,这是技术本身固有的。

如果在三角函数中使用 DECIMAL 值,它们会被隐式转换为浮点数,然后再转换回 DECIMAL。

正弦

返回以弧度表示的数值 X 的正弦值:

SELECT SIN(PI());   -- 1.2246063538224e-16 (实际上接近 0)

余弦

返回以弧度表示的 X 的余弦值:

SELECT COS(PI());   -- -1

正切

返回以弧度表示的数值 X 的正切值。注意结果非常接近零,但不完全为零。这是机器 ε 误差的一个例子。

SELECT TAN(PI());   -- -1.2246063538224e-16

反余弦

如果 X 在 -1 到 1 范围内,返回 X 的反余弦值:

SELECT ACOS(1);     -- 0
SELECT ACOS(1.01);  -- NULL

反正弦

如果 X 在 -1 到 1 范围内,返回 X 的反正弦值:

SELECT ASIN(0.2);   -- 0.20135792079033

反正切

ATAN(x) 返回单个数值的反正切值:

SELECT ATAN(2);     -- 1.1071487177941

ATAN2(X, Y) 返回两个变量 X 和 Y 的反正切值。它类似于计算 Y / X 的反正切值,但在数值上更稳健:当 X 接近零时也能正确计算,并且使用两个参数的符号来确定结果的象限。

最佳实践建议尽可能使用 ATAN2() 而不是 ATAN()。

SELECT ATAN2(1, 1);      -- 0.7853981633974483 (45 度)
SELECT ATAN2(1, -1);     -- 2.356194490192345 (135 度)
SELECT ATAN2(0, -1);     -- PI (180 度)

余切

返回 X 的余切值:

SELECT COT(12);          -- -1.5726734063977

转换

SELECT RADIANS(90);                     -- 1.5707963267948966
SELECT SIN(RADIANS(90));                -- 1
SELECT DEGREES(1), DEGREES(PI());       -- 57.29577951308232, 180

第 19.4 节:舍入(ROUND、FLOOR、CEIL)

将小数舍入为整数值

对于精确数值(如 DECIMAL):如果数字的第一位小数为 5 或更高,此函数将向远离零的方向舍入到下一个整数。如果该小数为 4 或更低,则向零方向舍入到最接近的整数。

SELECT ROUND(4.51);      -- 5
SELECT ROUND(4.49);      -- 4
SELECT ROUND(-4.51);     -- -5

对于近似数值(如 DOUBLE):ROUND() 函数的结果取决于 C 库;在许多系统上,这意味着 ROUND() 使用“四舍六入五成双”规则(向最近的偶数舍入):

SELECT ROUND(45e-1);     -- 4 (最近的偶数是 4)
SELECT ROUND(55e-1);     -- 6 (最近的偶数是 6)

向上舍入

使用 CEIL() 或 CEILING() 函数:

SELECT CEIL(1.23);       -- 2
SELECT CEILING(4.83);    -- 5

向下舍入

使用 FLOOR() 函数:

SELECT FLOOR(1.99);      -- 1

FLOOR 和 CEIL 分别向负无穷小方向或正无穷大方向舍入:

SELECT FLOOR(-1.01), CEIL(-1.01);   -- -2, -1
SELECT FLOOR(-1.99), CEIL(-1.99);   -- -2, -1

舍入到指定小数位数

SELECT ROUND(1234.987, 2);   -- 1234.99
SELECT ROUND(1234.987, -2);  -- 1200

关于向上/向下以及“5”的讨论同样适用。

第 19.5 节:乘方(POW)

使用 POW() 或 POWER() 函数计算 x 的 y 次方:

SELECT POW(2, 2);    -- 4
SELECT POW(4, 2);    -- 16

第 19.6 节:平方根(SQRT)

使用 SQRT() 函数。如果数字为负数,返回 NULL:

SELECT SQRT(16);     -- 4
SELECT SQRT(-3);     -- NULL

第 19.7 节:随机数(RAND)

生成随机数

使用 RAND() 函数生成 0 到 1 之间的伪随机浮点数:

SELECT i, RAND() FROM t;

结果类似:

i RAND()
1 0.6191438870682
2 0.93845168309142
3 0.83482678498591

范围内的随机数

要生成范围 a ≤ n ≤ b 内的随机数,可以使用以下公式:

FLOOR(a + RAND() * (b - a + 1))

例如,生成 7 到 12 之间的随机数:

SELECT FLOOR(7 + (RAND() * 6));

随机返回表中的行:

SELECT * FROM tbl ORDER BY RAND();

这些是伪随机数。

MySQL 中的伪随机数生成器在密码学上不安全。也就是说,如果你使用 MySQL 生成用作秘密的随机数,一个知道你使用 MySQL 的坚定攻击者将能够比你想象的更容易地猜测你的秘密。

第 19.8 节:绝对值和符号(ABS、SIGN)

返回数字的绝对值:

SELECT ABS(2);       -- 2
SELECT ABS(-46);     -- 46

数字的符号将其与 0 进行比较:

符号结果 说明 示例
-1 n < 0 SELECT SIGN(-3); → -1
0 n = 0 SELECT SIGN(0); → 0
1 n > 0 SELECT SIGN(42); → 1