SELECT中可直接用四则运算,但需警惕NULL导致结果为NULL、类型隐式转换不一致(如SQL Server+拼接字符串)、整数除法截断及除零错误,应优先用COALESCE处理NULL、NULLIF防除零、显式转换避免歧义。

SELECT中直接用+-*/做数值计算没问题,但要注意NULL和类型隐式转换
SQL标准支持在SELECT列表中对列或字面量直接使用四则运算符,比如price * 1.1算含税价、end_date - start_date算天数。但实际执行时,两个常见陷阱会悄无声息地破坏结果:
-
NULL参与任何算术运算结果仍是NULL(不是0,也不是报错),容易导致整行“消失”在聚合或条件过滤中 - 不同数据库对类型提升规则不一致:PostgreSQL严格要求操作数同类型,MySQL可能把字符串
'123'自动转成数字,而SQL Server在varchar列上用+会触发字符串拼接而非加法
避免NULL中断计算:优先用COALESCE而不是ISNULL或NVL
当被运算的字段可能为NULL时,别依赖数据库方言特有函数。标准SQL的COALESCE更可靠,且多数数据库都支持:
SELECT id, COALESCE(quantity, 0) * COALESCE(unit_price, 0) AS total_amount FROM orders;
这里COALESCE(quantity, 0)把NULL替换成0再参与乘法,确保total_amount总有值。注意:ISNULL(SQL Server)和NVL(Oracle)只接受两个参数,而COALESCE可链式处理多个备选值,语义更清晰。
除法要小心整数截断和除零错误
在PostgreSQL或SQL Server中,两个整数相除(如5 / 2)默认返回整数2,不是2.5;MySQL虽默认返回小数,但若列定义为INT,仍可能截断。除零则直接报错(如ERROR: division by zero):
- 强制转浮点:写成
amount::DECIMAL / NULLIF(qty, 0)(PostgreSQL)或CAST(amount AS FLOAT) / NULLIF(qty, 0)(SQL Server) - 用
NULLIF(divisor, 0)代替divisor,让除零时整个表达式返回NULL而非报错 - 别用
WHERE divisor != 0前置过滤——这会丢掉该行所有字段,而NULLIF保留行结构只让结果为空
不同数据库对+运算符的歧义最危险
在SQL Server和Sybase中,+既能加数字也能拼字符串;MySQL 8.0+对字符串用+会尝试转数字再加('1a' + '2b' → 3);而PostgreSQL和SQLite坚持+只用于数值,字符串拼接必须用||。所以:
- 永远显式转换:需要拼接就写
CONCAT(first_name, ' ', last_name),不要依赖first_name + ' ' + last_name - 数值计算前先确认列类型:
SELECT pg_typeof(price) FROM products LIMIT 1(PostgreSQL)或DESCRIBE products(MySQL) - 跨库迁移时,把所有
+替换成明确函数,避免上线后数据错乱
运算本身很简单,难的是预判数据质量、类型边界和目标数据库的脾气。写完每个算术表达式,先用NULL值和边界值(0、负数、超长小数)手工验一遍结果。

















