php保存小数变0,90%因mysql字段类型为int或无精度float导致截断,或default 0干扰;应改用decimal(m,d),显式绑定参数并统一sql mode。

PHP 保存小数到数据库变成 0,90% 是因为字段类型不支持小数或默认值干扰,不是 PHP 代码写错了。
检查 MySQL 字段类型是否为 INT 或无精度的 FLOAT
最常见原因:字段定义是 INT、TINYINT 或 FLOAT(没指定精度),MySQL 会自动截断小数部分或四舍五入为整数再存储。
-
INT类型完全不存小数,3.14写入后查出来就是3;如果 SQL 模式严格(如STRICT_TRANS_TABLES),甚至直接报错拒绝插入 -
FLOAT不带精度(如FLOAT而非FLOAT(10,2))在某些 MySQL 版本下行为不稳定,可能丢失精度或归零 - 正确做法:用
DECIMAL(M,D)存金额、比例等需精确小数的值(如DECIMAL(10,2)表示最多 10 位,其中 2 位小数);或用FLOAT(10,2)存对精度要求不高的浮点值
确认字段默认值是否为 0 且 PHP 传了 null 或空字符串
当 PHP 没给某个字段赋值(比如表单漏传、$_POST 键不存在),而该字段又设了 DEFAULT 0,MySQL 就会自动填 0 —— 看起来像“小数变 0”,其实是根本没写入你传的小数值。
- 排查方式:打印实际执行的 SQL(例如用
PDO::prepare()前 dump 绑定参数),确认变量是否为null、''或未定义 - PHP 中应显式判断:
isset($_POST['price']) && is_numeric($_POST['price']),避免把空字符串当0.00处理 - 建表时慎用
DEFAULT 0给小数字段;更安全的是DEFAULT NULL,并在应用层强制校验必填
注意 PHP 类型转换与 PDO 绑定参数的隐式行为
PHP 把字符串 "0.00" 或 "3.1415" 直接 bindParam 给 INT 类型字段时,PDO 可能按整型解析,导致小数被砍掉。
立即学习“PHP免费学习笔记(深入)”;
- 不要依赖 PDO 自动类型推断;显式指定参数类型:
$stmt->bindValue(':price', $price, PDO::PARAM_STR)(保持字符串原样)或PDO::PARAM_STR+ 字段设为DECIMAL - 避免用
(int)$price强转后再入库;改用floatval($price)或直接保留字符串(只要字段是DECIMAL,MySQL 能正确解析) - 调试时可临时用
var_dump(gettype($price), $price)确认传入值类型和内容
真正容易被忽略的是:开发环境 MySQL 的 SQL mode 往往比生产宽松(比如没开 STRICT_TRANS_TABLES),导致错误被静默吞掉——本地看着正常,上线就全变 0。务必在测试库和生产库用相同 SQL mode 验证。











