PHP怎么保存小数常见存后变整数_查字段长度与小数位【说明】

6次阅读

根本原因是mysql decimal字段未指定小数位(如decimal(10)默认numeric_scale=0),导致小数被截断;php端需用预处理绑定正确类型、避免Float计算误差,并检查sql_mode与表结构。

PHP怎么保存小数常见存后变整数_查字段长度与小数位【说明】

MySQL字段定义为DECIMAL但PHP存入后变整数

根本原因通常是字段定义没指定小数位,比如建表写了 DECIMAL(10) 而不是 DECIMAL(10,2)。MySQL在未显式声明小数位时,默认小数位为0,所有小数部分会被截断或四舍五入为整数。

实操建议:

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

  • SHOW CREATE table `table_name` 查看实际字段定义,确认是否含小数位参数
  • 修改字段:执行 ALTER TABLE `table_name` MODIFY column `price` DECIMAL(10,2);
  • 注意:修改过程中若已有数据含小数,且原字段是整型(如 int),需先转成带精度的 DECIMAL,否则小数丢失不可逆

PHP插入时小数被强制转整——检查mysqli_real_escape_stringpdo绑定类型

常见于手动拼SQL字符串时,把浮点变量直接拼进SQL,而PHP在字符串化过程中可能触发科学计数法或精度丢失;更隐蔽的是PDO预处理中未指定类型,导致PDO::PARAM_STR覆盖了数值精度。

实操建议:

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

  • 避免字符串拼接数值:"INSERT INTO t VALUES (" . $price . ")" → 改用预处理
  • PDO插入时显式绑定类型:$stmt->bindValue(':price', $price, PDO::PARAM_STR); 改为 PDO::PARAM_STR 仅当确定要字符串化;对金额优先用 PDO::PARAM_STR 或直接不传类型(让PDO自动推断)
  • 若用 mysqli,确保传入的是 float 类型值,而非字符串形式的数字(如 "19.99" 可能被当作字符串截断)

PHP浮点运算后存入MySQL精度异常——别依赖float/double做业务计算

PHP的 float 是IEEE 754双精度,本身存在二进制表示误差(如 0.1 + 0.2 !== 0.3)。若用 float 计算后再存入 DECIMAL(10,2),入库前可能已是 0.29999999999999999,MySQL按四舍五入规则存为 0.30 或截断为 0.29,取决于sql_mode设置。

实操建议:

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

  • 金额类运算统一用字符串或整数(单位“分”):$cents = (int)round($yuan * 100);
  • 必须用小数运算时,入库前格式化:number_format($value, 2, '.', ''),再作为字符串传入预处理
  • 检查MySQL的 sql_mode 是否含 STRICT_TRANS_TABLES,它会让超出精度的值报错而非静默截断

查字段长度与小数位的最快命令

别翻phpMyAdmin界面,直接用SQL定位问题字段:

SELECT COLUMN_NAME, DATA_TYPE, NUMERIC_PRECISION, NUMERIC_SCALE FROM INFORMATION_SCHEMA.COLUMNS  WHERE TABLE_SCHEMA = 'your_db_name'    AND TABLE_NAME = 'your_table_name'    AND COLUMN_NAME = 'your_column_name';

NUMERIC_PRECISION 是总位数,NUMERIC_SCALE 是小数位数。如果 NUMERIC_SCALE0NULL,说明当前字段不存小数。

容易被忽略的一点:有些ORM(如laravel Eloquent)在迁移中写 $table->decimal('price') 默认生成 DECIMAL(8,2),但若手动改过迁移又没跑 php artisan migrate:fresh,旧表结构不会自动更新。

text=ZqhQzanResources