str函数在sql server中存在精度陷阱,会四舍五入且小数处理不直观,仅适用于右对齐定宽报表输出;推荐用format、round配合cast或convert显式控制精度。

STR 函数在 SQL Server 中的精度陷阱
SQL Server 的 STR 函数不是“格式化数字”的安全选择——它会四舍五入,且对小数位数处理极不直观。比如 STR(9.99, 4, 2) 返回 '10.00'(长度超限导致整数部分被截断),而 STR(0.123, 5, 2) 得到 ' 0.12'(前面带空格,且小数被截断而非四舍五入)。这不是 bug,是它的设计逻辑:先按总宽度和小数位预留空间,再填充+四舍五入,最后左对齐空格。
替代方案:用 FORMAT 或字符串拼接控制精度
真正需要“固定小数位、不四舍五入截断、无前置空格”,应避开 STR:
-
FORMAT(value, 'N2')(SQL Server 2012+):返回带千分位和 2 位小数的字符串,但性能较差,且依赖当前语言环境(如小数点可能是逗号) -
CONVERT(varchar, ROUND(value, 2), 2)+ 字符串补零:更可控,例如RTRIM(CONVERT(varchar, ROUND(9.99, 2))) + '.' + RIGHT('00' + CAST(CAST((9.99 - FLOOR(9.99)) * 100 AS int) AS varchar), 2)——但太重,仅作思路参考 - 最实用的是
CONCAT(ROUND(value, 2), '.00')(若确定总是两位小数)或用CAST(ROUND(value, 2) AS decimal(10,2))转为精确小数类型后再转字符串,避免浮点误差
STR 的唯一可靠使用场景
仅当你要快速生成「右对齐、定宽、含空格填充」的报表式输出(如导出到固定列宽文本文件),且能接受四舍五入和整数溢出风险时,才用 STR:
- 总长度必须 ≥ 小数位数 + 2(至少留一位整数位 + 小数点)
- 小数位数不能超过 16(
STR内部限制) - 结果始终是
varchar,开头可能有空格,需用RTRIM清理,但注意RTRIM(STR(123, 5, 0))得到'123'(非'123 '),因为STR在整数位不足时会压缩空格
别忽略隐式类型转换带来的精度丢失
即使你绕开了 STR,直接写 CAST(123.456 AS varchar) 或 CONVERT(varchar, 123.456),SQL Server 默认只保留最多 6 位有效数字(如 123.456 → '123.456' 没问题,但 1234567.89 → '1.23457e+006')。必须显式指定精度:CONVERT(varchar, CAST(1234567.89 AS decimal(10,2))) 才能得到 '1234567.89'。
真正难的不是选函数,而是想清楚:你要的是显示格式、存储精度,还是传输协议要求?三者目标冲突时,STR 几乎从来不是答案。











