Php 使用PDO更新数据为什么它不工作

Php 使用PDO更新数据为什么它不工作,php,mysql,sql,pdo,Php,Mysql,Sql,Pdo,我做错了什么?因为如果我这样做,它会起作用: <?php $sTable = "mytable"; $colUpdate = $_GET['field'];// database field name $valUpdate = $_GET['val']; // the long string ,can be non-English $rowID = $_GET['id']; //number $pdo = PDO2::getInstance(); $pdo

我做错了什么?因为如果我这样做,它会起作用:

<?php
$sTable = "mytable";    

$colUpdate = $_GET['field'];// database field name
$valUpdate = $_GET['val']; // the long string ,can be non-English   
$rowID = $_GET['id']; //number

    $pdo = PDO2::getInstance();
    $pdo->exec('SET NAMES utf8'); // for utf-8

    $sql = "UPDATE $sTable
            SET $colUpdate =:valUpdate
            WHERE id =:rowID ";      
    $req = $pdo->prepare($sql);
    $req->bindValue(":valUpdate",  $valUpdate);
    $req->bindValue(":rowID",  $rowID);

    $req->execute();
    $req->closeCursor();        
   ?>

您的代码中有几个问题:

  • 您正在使用单例
  • 您没有检查错误
  • 您直接传递GET变量
  • 让我们逐一谈谈,好吗

    1.您正在使用单例 ,它们设置在全局空间中,这使得您的应用程序不稳定、不可靠且不稳定。此外,如果您需要另一个数据库连接,您会怎么做

    解决方案 使用新的PDO实例

    2.您没有检查错误 代码中没有任何错误检查,因此如果出现错误,它将被默默地忽略

    解决方案 在PDO的构造函数中或使用
    setAttribute
    PDO::ATTR\u ERRMODE
    设置为
    PDO::ERRMODE\u EXCEPTION
    。它还帮助将
    PDO::EMULATE\u PREPARES
    设置为
    false

    3.您将GET变量直接传递到查询中 您直接在查询中传递
    $colUpdate
    ,即使您正在准备语句,直接传递到查询字符串中的变量也不会转义

    解决方案 将其传递到占位符中,并绑定该值。此外,如果需要用户输入来确定要更新的列,则结构很可能存在缺陷

    在所有这些之后,我得到了以下代码:

     <?php
        $sTable = "mytable";
        $pdo = PDO2::getInstance();
        $colUpdate = $_GET['field'];
        $valUpdate = $_GET['val'];      
        $rowID = $_GET['id'];
    
        $sQuery = " UPDATE $sTable SET  $colUpdate = '$valUpdate' WHERE  id = $rowID";
        $req = $pdo->prepare($sQuery);
        $req->execute();
        $req->closeCursor();    
    ?>
    

    你做错了什么:你发布了一个问题,但没有描述问题,没有包含任何错误。你没有在代码中对查询进行任何错误检查。因此,当查询失败时,代码中断也就不足为奇了。有关如何从PDO中获取第一个代码框中最后一行
    bindValue
    execute()
    之间的错误消息,请参见:
    $err=$req->errorInfo();echo$err[2]
    并告诉我们它是什么意思。您是否尝试指定绑定的参数类型:
    PDO::PARAM_STR
    PDO::PARAM_INT
    ?顺便说一句,您将
    $colUpdate
    直接插入到查询中的事实完全违背了使用准备语句的目的。它直接从
    $\u GET
    派生而来,没有任何过滤或验证,因此对SQL注入攻击是一个非常开放的调用。为此,最好的方法是通过
    switch()
    语句传递
    $\u GET['field']
    ,其中
    cases
    是表的名称。这将强制
    $colUpdate
    成为开关中的
    情况之一,而不是其他情况。为了您的安全,请这样做!
    
    <?php
    /*
     * Variable Initialization
     */
    /** @var $table_name string Name of the table to insert */
    $table_name = "mytable";
    
    /**
     * @var $field_to_update string Name of field to update
     * @deprecated Should not be used! Database restructuring needed!
     */
    $field_to_update = mysql_real_escape_string($_GET['field']); //At least escape it!
    
    /** @var $value_to_insert string */
    $value_to_insert = $_GET['val'];
    
    /** @var $row_id integer */
    $row_id = $_GET['id'];
    
    $pdo = new PDO("mysql:host=localhost;dbname=database_name", "user", "password");
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    $pdo->exec('SET NAMES utf8'); // for utf-8
    
    $sql = <<<MySQL
    UPDATE $table_name
        SET $field_to_update = :valUpdate
        WHERE id = :rowID
    MySQL;
    
    $req = $pdo->prepare($sql);
    $req->bindValue(":valUpdate", $value_to_insert, PDO::PARAM_STR);
    $req->bindValue(":rowID", $row_id, PDO::PARAM_INT);
    
    $req->execute();