STR函数本质是格式化为固定长度字符串,非类型转换函数;默认右对齐、左补空格,对超长数字返回“*”,且不处理科学计数法输入。

SQL Server里用STR转科学计数法数字会截断或补空格?
STR本质是格式化为固定长度字符串,不是类型转换函数。它默认右对齐、左补空格,且会四舍五入——比如STR(1234567890123456789.123, 20, 3)结果是" 1234567890123456789.123"(注意开头一堆空格),而超长数字直接变成"*"。它不识别科学计数法输入,只处理数值本身;若原始列是float存了1.23E+15,STR接收到的已是近似值,精度早丢了。
实操建议:
- 永远显式指定长度和小数位,例如
STR(@val, 30, 10),避免默认STR(@val)只给10位总长导致溢出 - 用
LTRIM清除前导空格:LTRIM(STR(@val, 30, 10)) - 对可能超范围的
float,先用ISNUMERIC或尝试TRY_CONVERT(decimal(38,10), @val)兜底,再转字符串
SQL Server 2012+用FORMAT输出可读字符串更稳,但要注意性能和区域
FORMAT能真正按“样式”控制输出,比如把1.23456789E+15转成"1234567890000000"或"1,234,567,890,000,000",但它底层调用.NET,比STR慢5–10倍,且受LANGUAGE或会话DATEFORMAT影响。
实操建议:
- 数字格式用
'G17'(通用格式,最多17位有效数字)保留浮点精度:FORMAT(@val, 'G17') - 要彻底禁用科学计数法,用
'F0'强制小数位为0,但需确保数值不过大(否则报错);稳妥做法是TRY_FORMAT(@val, 'G17')防异常 - 避免在WHERE或JOIN条件里用
FORMAT,它无法走索引,也拖慢大结果集
PostgreSQL或MySQL用户别找STR/FORMAT——它们压根没有
PostgreSQL用to_char,MySQL用FORMAT()(注意:MySQL的FORMAT是千分位函数,不是SQL Server那个),两者行为完全不同。例如PostgreSQL中to_char(1.23e15, 'FM999999999999999999999999999')才能压制科学计数法,但字段超长就报错;MySQL的FORMAT(1.23e15, 0)输出"1,230,000,000,000,000",逗号不可配,且会四舍五入。
实操建议:
- PostgreSQL优先用
CAST(col AS text)或col::text,对double precision列,它默认用足够位数输出,一般不显科学计数法 - MySQL若必须去E,先转
DECIMAL再转字符串:CAST(CAST(col AS DECIMAL(30,10)) AS CHAR),但要注意DECIMAL溢出风险 - 跨数据库项目,别依赖数据库函数做数字格式化,放到应用层更可控
真正安全的方案:源头控制数据类型,而不是硬转
科学计数法显示问题,90%源于用了float或real存本该精确的数字(比如ID、金额、序列号)。一旦存成浮点,精度丢失不可逆,后续任何STR或FORMAT都只是“修修补补”。
实操建议:
- 整数ID、货币、计数器一律用
BIGINT、DECIMAL(p,s),别碰float - 如果上游API或导入文件给了科学计数法字符串(如
"1.23E+10"),入库前用应用代码解析成整型/定点数,再INSERT——数据库不负责“猜意图” - 查出来要展示?加个计算列:
ALTER TABLE t ADD display_id AS CAST(id_col AS VARCHAR(30)) PERSISTED,避免每次SELECT都调函数
最麻烦的从来不是怎么转,而是发现float列里存着9999999999999999和10000000000000000其实被存成了同一个值。










