PDO语句更新0个值,而不是null或为空

问题描述

我正在执行PDO更新语句,但是它在空值上输入0。

  • 我想要一个空值输入null
  • 我希望零值输入零

这是我的代码

include 'dbconfig.PHP';

$id = $_POST['id'];
$data = $_POST['data'];

try {
    $options = [
    \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,\PDO::ATTR_EMULATE_PREPARES => false,];
    $pdo = new PDO("MysqL:charset=utf8mb4;host=$servername;dbname=$dbname",$username,$password);
    
    $setStr = "";

    $values = array();

    foreach($data as $field => $value) {
        $setStr .= "$field=:$field,";
        $values[$field] = $value;
    }

    $setStr = rtrim($setStr,",");


    $values['id'] = $id;
    $stmt = $pdo->prepare("UPDATE products SET $setStr WHERE id = :id");
    $stmt->execute($values);


    $count = $stmt->rowCount();

    if ($count > 0) {
        echo json_encode(array('response'=>'success','message'=>'Product ID # '.$id." successfully updated."));
    }else{
        echo json_encode(array('response'=>'danger','message'=>'Product not successfully updated'));
    }

}catch(PDOException $e){
    
    echo json_encode(array('response'=>'danger','message'=>$e->getMessage()));
}
    $conn = null;

做到这一点的最佳方法是什么?谢谢

解决方法

检查循环中是否有空字符串,并将其转换为null

    foreach($data as $field => $value) {
        $setStr .= "$field=:$field,";
        $values[$field] = $value === "" ? null : $value;
    }
,

PDOStatement :: execute认为每个参数都是一个字符串。在某些数据库中,驱动程序可以毫无问题地进行处理,但是,如果要专门键入值,则需要使用bindValue。通过这种键入,我们可以将null(或空)值键入到database-null类型(而不是列的默认值)-请参见我的bindEmptyAsNull函数。

此外,由于我使用的是 trusted 列名称,因此可以安全地使用您的$setStr模式来构建更新参数,但是请注意,您可能不想更新$dangerData关联数组中未包含的列(按原样,如果未提交,则该列将被清除)。

<?php

//... your setup code,including $pdo

// List all the names of the columns in the products table here - you havent' provided enough info so I'm guessing
$keys=["name","cost","weight_grams"];
$dangerId = $_POST['id'];
$dangerData = $_POST['data'];

/**
 * Convert null values into PARAM_NULL types,not
 * @param $type Should be one of the [PDO::PARAM_*](https://www.php.net/manual/en/pdo.constants.php) constants
 */
function bindEmptyAsNull($stmt,$name,$value,$type=PDO::PARAM_STR) {
    //If you want empty string to be considered null too:
    //if ($value===null || $value==="") {
    if ($value===null) {
        //Note the column needs to support null types
        $stmt->Value($name,null,PDO::PARAM_NULL);
    } else {
        $stmt->bindValue($name,$type);
    }
}

//Build the set string
$setStr='';
foreach($keys as $col) {
    $setStr.=$col.'=:'.$col.',';
}
$setStr=substr($set,-1);//Remove the trailing comma

//Create the statement
$stmt=$pdo->prepare("UPDATE products SET $setStr WHERE id=:id");

//Bind the danger values
// NOTE: The only way you could automate this (re-read the keys array) is to also have an
// associative array of key:type mapping too
$stmt->bindValue(":id",$dangerId,PDO::PARAM_INT);
bindEmptyAsNull($stmt,":name",$dangerData["name"]);
bindEmptyAsNull($stmt,":cost",$dangerData["cost"]);
bindEmptyAsNull($stmt,":weight_grams",$dangerData["weight_grams"],PDO::PARAM_INT);

$stmt->execute();
// .. Further processing