点击提交后数据库库存更新异常:输入数量致负库存问题排查
问题原因及修复方案
核心问题
库存变成负数的直接原因是没有正确获取对应商品的当前库存值:
- 代码里执行了查询
product_stock表的语句,但完全没从查询结果中取出数据赋值给$row变量 - 未初始化的
$row['qty_stock']会被视为空值,计算$stock = $row['qty_stock'] - $qty时,相当于0 - 输入数量,最终得到负数
修复步骤
1. 正确获取对应商品的库存数据
不要查询整个库存表,只查询当前操作商品的库存,同时取出结果赋值:
// 替换原查询语句,仅查询当前商品的库存 $stock_query = mysqli_query($link, "SELECT qty_stock FROM product_stock WHERE product_name='$product'"); // 取出查询结果到$row变量 $row = mysqli_fetch_assoc($stock_query); // 检查是否查询到商品,避免无数据时报错 if($row) { $stock = $row['qty_stock'] - $qty; $update_que = "UPDATE product_stock SET qty_stock='$stock' WHERE product_name='$product'"; $run_update = mysqli_query($link,$update_que); }
2. 修复SQL注入漏洞(关键优化)
你的代码直接将POST参数拼入SQL语句,存在严重的安全风险,必须用mysqli预处理语句重构:
// 插入采购记录的预处理示例 $insert_stmt = mysqli_prepare($link, "INSERT INTO purchasedproducts (invoice_id, productname, quantity, amtpaid) VALUES (?, ?, ?, ?)"); mysqli_stmt_bind_param($insert_stmt, "isii", $invoice, $product, $qty, $amtpaid); mysqli_stmt_execute($insert_stmt); // 查询库存的预处理示例 $stock_stmt = mysqli_prepare($link, "SELECT qty_stock FROM product_stock WHERE product_name=?"); mysqli_stmt_bind_param($stock_stmt, "s", $product); mysqli_stmt_execute($stock_stmt); mysqli_stmt_bind_result($stock_stmt, $current_stock); mysqli_stmt_fetch($stock_stmt); // 更新库存的预处理示例 if(isset($current_stock)) { $new_stock = $current_stock - $qty; $update_stmt = mysqli_prepare($link, "UPDATE product_stock SET qty_stock=? WHERE product_name=?"); mysqli_stmt_bind_param($update_stmt, "is", $new_stock, $product); mysqli_stmt_execute($update_stmt); }
3. 增加错误排查逻辑
可以添加SQL执行错误提示,方便排查问题:
if(!$run_update) { echo "库存更新失败: " . mysqli_error($link); exit; }
完整修复后的代码示例
<?php include 'config.php'; $invoice = $_POST['invoiceid']; if(isset($_POST['submit'])){ $checked_array=$_POST['prod']; foreach ($_POST['prodname'] as $key => $value) { if(in_array($_POST['prodname'][$key], $checked_array)){ $product=$_POST['prodname'][$key]; $price= $_POST['price'][$key]; $qty= $_POST['qty'][$key]; $amtpaid = $price * $qty; // 插入采购记录(预处理防注入) $insert_stmt = mysqli_prepare($link, "INSERT INTO purchasedproducts (invoice_id, productname, quantity, amtpaid) VALUES (?, ?, ?, ?)"); mysqli_stmt_bind_param($insert_stmt, "isii", $invoice, $product, $qty, $amtpaid); mysqli_stmt_execute($insert_stmt); // 查询当前商品库存 $stock_stmt = mysqli_prepare($link, "SELECT qty_stock FROM product_stock WHERE product_name=?"); mysqli_stmt_bind_param($stock_stmt, "s", $product); mysqli_stmt_execute($stock_stmt); mysqli_stmt_bind_result($stock_stmt, $current_stock); mysqli_stmt_fetch($stock_stmt); // 更新库存(仅当查询到库存时执行) if(isset($current_stock)) { $new_stock = $current_stock - $qty; $update_stmt = mysqli_prepare($link, "UPDATE product_stock SET qty_stock=? WHERE product_name=?"); mysqli_stmt_bind_param($update_stmt, "is", $new_stock, $product); mysqli_stmt_execute($update_stmt); } else { echo "未找到商品「$product」的库存记录"; } } } } header('Location: sample.php'); ?>
内容的提问来源于stack exchange,提问作者Lyka C
相关产品推荐
相关产品推荐

