PHP怎么保存小数入库不丢值_mysqli_real_escape或PDO参数绑定【操作】

1次阅读

小数入库丢失精度的根源在于php浮点运算、mysql字段类型(须用DECIMAL而非Float/double)、传值方式及配置参数;应使用pdo绑定字符串类型+DECIMAL字段+严格模式校验。

PHP怎么保存小数入库不丢值_mysqli_real_escape或PDO参数绑定【操作】

小数入库丢失精度,不是转义函数的问题

mysqli_real_escape_string 或手动拼 SQL 时对小数做转义,根本不能解决精度丢失——它只处理字符串中的特殊字符,不干预数值类型转换或浮点截断。真正出问题的地方在 PHP 浮点运算、MySQL 字段定义、以及你传值的方式。

必须用 PDO 参数绑定 + 正确定义字段类型

参数绑定本身不保证精度,但它是避免隐式字符串转浮点的第一步。关键在于:绑定后 MySQL 是否按你期望的类型接收并存储。常见错误是 PHP 把 3.1415926 当作 float 传入,而字段是 FLOATDOUBLE,直接进坑。

  • MySQL 字段必须定义为 DECIMAL(M,D)(如 DECIMAL(10,6)),不能用 FLOAT/DOUBLE
  • PDO 绑定时,显式指定类型:$stmt->bindValue(':price', $value, PDO::PARAM_STR) —— 强制当字符串传,避免 PHP float 解析失真
  • 如果值来自表单输入,先用 filter_var($input, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION) 清洗,再验证是否匹配正则 /^d+(.d+)?$/

mysqli_real_escape_string 对小数完全无效且危险

这个函数只该用于未绑定的字符串拼接场景,而且仅限于字符串内容转义。如果你对一个 float 变量调用它:mysqli_real_escape_string($conn, 3.1415926),PHP 会先把它转成字符串(可能已丢精度),再转义——既没意义又掩盖了根源问题。

  • 不要对数字类型变量使用 mysqli_real_escape_string
  • 若坚持用 mysqli,必须用 mysqli_prepare + bind_param,且类型符用 'd'(double)仅当字段确实是 DECIMAL 且你确认 PHP 浮点没提前失真;更稳妥仍是传 's' + 字符串
  • 注意 bind_param('d', $val) 中的 $val 若是 PHP float,传入前就可能已是 3.1415926000000003

最容易被忽略的环节:PHP ini 和 MySQL 系统变量

即使代码全对,serialize_precision(PHP 7.1+ 默认 -1)和 MySQL 的 sql_mode 也会影响结果。比如开启 STRICT_TRANS_TABLES 时,超长小数会被截断报错;而关闭时静默截断,你以为存进去了,其实早丢了。

立即学习PHP免费学习笔记(深入)”;

  • 检查 PHP 配置:ini_get('serialize_precision') 应为 -1(保留完整精度输出)
  • 检查 MySQL:select @@sql_mode;,确保不含 ALLOW_INVALID_DATES 类宽松模式
  • 插入后立刻 SELECT 出来对比原始字符串值,别只信 PHP echo
text=ZqhQzanResources