【问题标题】:MySQL update, skip blank fields with PDOMySQL 更新,使用 PDO 跳过空白字段
【发布时间】:2014-01-18 22:15:39
【问题描述】:

我想通过下面的表格更新 MySQL 行。该表单原样工作得很好,但是,如果我将字段留空,它也会将 MySQL 中的字段更改为空白。我想更新 sql 但跳过所有空白字段。

我已经阅读了一些这样做的方法,但它们似乎不合逻辑。 IE。在 sql 字符串本身中使用 if 语句。 (让 MySQL 完成应该在 PHP 中完成的工作)。

if($_SERVER['REQUEST_METHOD'] != 'POST')
{   
 echo '<form method="post" action="">
    ID: <input type="text" name="a" /><br>
    Program: <input type="text" name="b" /><br>
    Description: <textarea row="6" cols="50" name="c"></textarea><br>
    Cost: <input type="text" name="d"><br>
    <input type="submit" value="Add Link" />
 </form>';
}


try {
  $dbh = new PDO($dsn, $user, $pass);
  $dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
  $stmt = $dbh->prepare('UPDATE links SET Program = :program , Descr = :descr, Cost = :cost WHERE Id= :id');

  $stmt->bindParam(":id", $_POST["a"]);
  $stmt->bindParam(":program", $_POST["b"]);
  $stmt->bindParam(":descr", $_POST["c"]);
  $stmt->bindParam(":cost", $_POST["d"]);
  $stmt->execute();
  if (!$stmt) {
    echo "\nPDO::errorInfo():\n";
    print_r($dbh->errorInfo());}
    $dbh = null;

  }
}catch (PDOException $e) {
  print "Error!: " . $e->getMessage() . "<br/>";
  die();
}

【问题讨论】:

  • 如果该字段没有值,您的意思是要将该字段设置为NULL
  • Evening Robbert,不,如果字段为空,我希望它被忽略。因此,在一天结束时,数据库中的空白字段保持不变。
  • 只是为了澄清一点(一开始就应该这样做)。如果我填写了上面的表格,但将费用字段留空。我希望 php/mysql 使用给定的信息更新数据库,但不更新表单中的空白字段。谢谢
  • 我认为if 语句是您唯一的解决方案。
  • 您应该使用!empty(trim($_POST['a']))验证输入字段

标签: php mysql forms pdo


【解决方案1】:

在 PDO 中使用未命名参数进行动态查询并将它们作为数组传递给 execute() 会更容易。除非与 id 一起传递至少 1 个参数,否则该语句将不会被执行。我留在了派生语句的回声和数组的转储中。

示例语句

UPDATE `links` SET `Program` = ? , `Cost` = ? WHERE `Id` = ? 

示例数组

Array ( [0] => 2 [1] => 3 [2] => 2 )


if(isset($_GET['a'])){
$id = $_GET['a'];
$program = isset($_GET['b']) ? $_GET['b'] : NULL;
$descr = isset($_GET['c']) ? $_GET['c'] : NULL;
$cost= isset($_GET['d']) ? $_GET['d'] : NULL;
$params =array();
$sql = "UPDATE `links` SET "; //SQL Stub
if (isset($program)) {
    $sql .= " `Program` = ? ,";
    array_push($params,$program);   
}
if (isset($descr)) {
    $sql .= " `Descr` = ? ,";
    array_push($params,$descr); 
}
if (isset($cost)) {
    $sql .= " `Cost` = ? ,";
    array_push($params,$cost);  
}
$sql = substr($sql, 0, -1);//Remove trailing comma
if(count($params)> 0){//Only execute if 1 or more parameters passed.
    $sql .= " WHERE `Id` = ? ";
    array_push($params,$id);
    echo $sql;//Test
    print_r($params);//Test
    $stmt = $dbh->prepare($sql);
        $stmt->execute($params);
}
}

【讨论】:

    【解决方案2】:

    这样的东西应该可以工作

    .
    .
    .
    $q = array();
    if(trim($_POST["b"]) !== ""){
        $q[] = "Program = :program";
    }
    if(trim($_POST["c"]) !== ""){
        $q[] = "Descr = :descr";
    }
    if(trim($_POST["d"]) !== ""){
        $q[] = "Cost = :cost";
    }
    if(sizeof($q) > 0){//check if we have any updates otherwise don't execute
        $query = "UPDATE links SET " . implode(", ", $q) . " WHERE Id= :id";
        $stmt = $dbh->prepare($query);
        $stmt->bindParam(":id", $_POST["a"]);
        if(trim($_POST["b"]) !== ""){
            $stmt->bindParam(":program", $_POST["b"]);
        }
        if(trim($_POST["c"]) !== ""){
            $stmt->bindParam(":descr", $_POST["c"]);
        }
        if(trim($_POST["d"]) !== ""){
            $stmt->bindParam(":cost", $_POST["d"]);
        }
        $stmt->execute();
    }
    .
    .
    .
    

    【讨论】:

    • 这非常有效。昨晚我沿着这些路线寻找,但我自己错过了 if bindparam 语句。谢谢朋友。
    【解决方案3】:

    更改语句:

    $stmt = $dbh->prepare('UPDATE links SET Program = :program , Descr = :descr, Cost = :cost WHERE Id= :id');
    

    如下:

    $stmt = $dbh->prepare('UPDATE links SET Program = IF(trim(:program)="", Program, :program) , Descr = IF(trim(:descr)="", Descr, :descr), Cost = IF(trim(:cost)="", Cost, :cost) WHERE Id= :id');
    

    【讨论】:

    • 我喜欢这个想法,但是我更喜欢让 php 准备查询,然后 mysql 执行它。而不是mysql做额外的工作。我的思路是发送给 mysql 或要求 mysql 获得我们想要的结果的信息越少越好。也就是说,这种情况也可以!感谢 Rajesh 的意见。
    • 这种策略肯定会增加LOC,这也增加了整个操作的时间复杂度。所以在 php 端处理它并不总是有益的。
    • 非常正确。我想这取决于服务器环境。 IE。共享托管 Mysql Server 和另一个 IIS/Apache 服务器。如果共享 MySql 服务器的负载比 web 服务器高。 PHP会更有效。但是,如果对 Web 服务器的需求更高,则情况正好相反。然后使用 mysql 服务器来执行更多的 php 任务将是有意义的。这个逻辑当然规模很大。
    • 哇。大大解释了。当然有两个方面。
    【解决方案4】:

    检查帖子字段是否为空: 如果任何字段数据为空,它将跳过更新查询。

    If( $_POST["a"] && $_POST["b"] && $_POST["c"] && $_POST["d"]){
    
            try {
              $dbh = new PDO($dsn, $user, $pass);
              $dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
              $stmt = $dbh->prepare('UPDATE links SET Program = :program , Descr = :descr, Cost = :cost WHERE Id= :id');
    
              $stmt->bindParam(":id", $_POST["a"]);
              $stmt->bindParam(":program", $_POST["b"]);
              $stmt->bindParam(":descr", $_POST["c"]);
              $stmt->bindParam(":cost", $_POST["d"]);
              $stmt->execute();
              if (!$stmt) {
                echo "\nPDO::errorInfo():\n";
                print_r($dbh->errorInfo());}
                $dbh = null;
    
              }
            }catch (PDOException $e) {
              print "Error!: " . $e->getMessage() . "<br/>";
              die();
            }
    
    
        }
    

    Option2 更新除空之外的所有字段:

    try {
                $sql ="UPDATE links SET ";
                if($_POST["a"])
                    $sql .=" Program = :program ,";
                if($_POST["b"])
                    $sql .=" Descr = :descr ,";
                if($_POST["c"])
                    $sql .=" Cost = :cost ,";
    
                $sql = rtrim($sql,',');
                $dbh = new PDO($dsn, $user, $pass);
                $dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
                $stmt = $dbh->prepare($sql);
                if($_POST["a"])
                    $stmt->bindParam(":id", $_POST["a"]);
                if($_POST["b"])
                    $stmt->bindParam(":program", $_POST["b"]);
                if($_POST["c"])
                    $stmt->bindParam(":descr", $_POST["c"]);
    
                $stmt->execute();
    
                if (!$stmt) {
                    echo "\nPDO::errorInfo():\n";
                    print_r($dbh->errorInfo());}
                $dbh = null;
    
            }
            catch (PDOException $e) {
        print "Error!: " . $e->getMessage() . "<br/>";
        die();
    }
    

    【讨论】:

    • Isset 只告诉它是否已设置,而不告诉它是否有任何值
    • 如果任何字段留空,这将不允许更新任何字段,对吗?我正在寻找使用给定信息更新数据库,但不更新同一查询中的空白字段。
    • 谢谢@Class 我正在更新这个答案
    • 昨晚我在解雇之前一直在使用 option2,但我遇到的问题是使用上述场景将“WHERE id =:Id”注入 SQL 字符串而不使用 implode . Class 提供的答案正是基于这个思路。感谢 Awlad 的帮助!
    猜你喜欢
    • 2016-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多