【问题标题】:PDO Update Statement won't workPDO 更新声明不起作用
【发布时间】:2017-09-06 14:42:27
【问题描述】:

我对 PDO 声明“更新”有疑问。我想使用以下代码更新数据库中的现有列:

<?php
$sql="UPDATE $title SET header = $header;";

for($co=1,$arr=0;$co<=$count;$co++,$arr++)
{
   $sql .= "UPDATE $title SET theme$co = :theme, content$co = :content;";
   $insert = array('theme' => $theme[$arr], 'content' => $content[$arr]); 

   $statement = $pdo->prepare($sql);
   $statement->execute($insert);
}
?>

问题是,当这段代码完成后,数据库中什么也没有发生。 数组“主题”和“内容”只包含一些用户写下来的文本。根据用户输入的主题/内容的数量,您获得的数组越多。例如:

$theme1="a";
$theme2="b";
$content1="abc";
$content2="def";

因此,在 DB 中,已经创建了与主题和内容数组同名的列。现在我要做的是,将例如 $theme1 的值插入“theme1”列,将 $content1 的值插入“content1”列等等......

我已经试过改了

$sql .= to $sql =

并将其作为单个查询执行。但这也没有用。

我没有使用“插入”语句,因为它总是会在数据库中创建一个新行,所以它看起来像 this
正如您在屏幕截图中看到的那样,这是完全错误的,我试图将所有内容集中在一行中。这就是为什么我尝试更新而不是插入。 由于创建表及其所有列都可以使用 PDO 正常工作,我想知道为什么 Update 根本不起作用。

编辑:变量“title”没有拼写错误,我是德国人,这对我来说是正确的。由于您可以根据需要命名变量,因此我可以用我的母语来命名。但无论如何感谢你告诉我,我试图用英文单词替换所有德语变量,但我错过了那个,所以我现在改变了。

【问题讨论】:

  • 这在代码的开头 $sql="UPDATE $titel SET header = $header;";然后是这个 $sql .= "UPDATE $title SET theme$co = :theme, content$co = :content;";在for循环中可能会导致mysql异常,因为第一个更新语句无效
  • 检查变量$titel 的拼写。应该是$title
  • @AaronK。不,OP 在两个地方都拼错了。
  • 单个查询中的多次更新无效。是的,您可以在单个查询中多次更新值,但在单个查询中使用多次 UPDATE 关键字无效

标签: php mysql pdo


【解决方案1】:

这是我的解决方案。它包含错误报告/显示以及与 exception handling 结合使用 PDO 准备语句所涉及的所有正确步骤。

代码被注释了。

尝试习惯使用sprintf function。有了它,您可以优雅地构建非常复杂的 sql 语句。

祝你好运!

<?php

/*
 * ============================================================
 * Set error reporting level and display errors on screen.
 * Use it ONLY ON A DEVELOPMENT SYSTEM, NEVER ON PRODUCTION!
 * If you activate it on a live system, then the users will see
 * all the errors of your system. And you don't want this!
 * ============================================================
 */
error_reporting(E_ALL);
ini_set('display_errors', 1);

/*
 * User variables.
 */

// "table name" not "title" ;-)
$tableName = 'your_table';

// "Themes" not "theme" ;-)
$themes = array('t1', 't2', 't3', 't4', 't5');

// "Contents" not "content" ;-)
$contents = array('c1', 'c2', 'c3', 'c4', 'c5');

// Counter for building the sql statement's assignment list
// and the input parameters list for the sql statement's markers.
$count = 5;

try {
    /*
     * Create a PDO instance as db connection to a MySQL db.
     */
    $connection = new PDO(
            'mysql:host=localhost;port=3306;dbname=yourDb;charset=utf8'
            , 'yourDbUsername'
            , 'yourDbPassword'
    );

    /*
     * Assign the driver options to the db connection.
     */
    $connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
    $connection->setAttribute(PDO::ATTR_PERSISTENT, TRUE);

    /*
     * Build the sql statement and fill the input parameters list.
     * 
     * ------------------------------------------------------------------------
     * Notes:
     * 
     *  - Quote: "You cannot use a named parameter marker of the same name more 
     *    than once in a prepared statement, unless emulation mode is on."
     *    See: http://php.net/manual/de/pdo.prepare.php
     * 
     *  - DON'T use semicolon at the end of sql statements in PHP!
     * ------------------------------------------------------------------------
     */
    // Sql statement's assignment list. Array of "column-name = :column-marker, ..." assignments.
    $assignments = array();

    // Input parameters list, e.g the values for the sql statement markers.
    $bindings = array();

    // Note: Use one iteration variable for both operations!
    for ($i = 1; $i <= $count; $i++) {
        // Add sql assignments to assignment list.
        $assignments[] = sprintf('theme%s = :theme%s, content%s = :content%s', $i, $i, $i, $i);

        // Add corresponding input parameter values to bindings list.
        $bindings[':theme' . $i] = $themes[$i - 1];
        $bindings[':content' . $i] = $contents[$i - 1];
    }

    // Final sql statement.
    $sql = sprintf(
            'UPDATE %s 
            SET header = %s
            %s'
            , $tableName
            , $header
            , $assignments ? ',' . implode(',', $assignments) : ''
    );

    /*
     * Prepare and validate the sql statement.
     * 
     * --------------------------------------------------------------------------------
     * If the database server cannot successfully prepare the statement, PDO::prepare() 
     * returns FALSE or emits PDOException (depending on error handling settings).
     * --------------------------------------------------------------------------------
     */
    $statement = $connection->prepare($sql);

    if (!$statement) {
        throw new UnexpectedValueException('The sql statement could not be prepared!');
    }

    /*
     * Bind the input parameters to the prepared statement.
     * 
     * -----------------------------------------------------------------------------------
     * Unlike PDOStatement::bindValue(), when using PDOStatement::bindParam() the variable 
     * is bound as a reference and will only be evaluated at the time that 
     * PDOStatement::execute() is called.
     * -----------------------------------------------------------------------------------
     */
    foreach ($bindings as $key => $value) {
        // Get the name of the input parameter by its key in the bindings array.
        $inputParameterName = is_int($key) ? ($key + 1) : (':' . ltrim($key, ':'));

        // Get the PDO::PARAM_* constant, e.g the data type of the input parameter, by its value.
        $inputParameterDataType = PDO::PARAM_STR;
        if (is_int($value)) {
            $inputParameterDataType = PDO::PARAM_INT;
        } elseif (is_bool($value)) {
            $inputParameterDataType = PDO::PARAM_BOOL;
        }

        // Bind the input parameter.
        $bound = $statement->bindValue($inputParameterName, $value, $inputParameterDataType);

        if (!$bound) {
            throw new UnexpectedValueException('An input parameter can not be bound!');
        }
    }

    /*
     * Execute the prepared statement.
     * 
     * ------------------------------------------------------------------
     * PDOStatement::execute returns TRUE on success or FALSE on failure.
     * ------------------------------------------------------------------
     */
    $executed = $statement->execute();

    if (!$executed) {
        throw new UnexpectedValueException('The prepared statement can not be executed!');
    }

    /*
     * Get number of affected rows.
     */
    $numberOfAffectedRows = $statement->rowCount();

    /*
     * Display results.
     */
    echo $numberOfAffectedRows;

    /*
     * Close connection.
     */
    $connection = NULL;
} catch (PDOException $exc) {
    echo $exc->getMessage();
    // Log the whole exception object to a file.
    // $logger->log($exc);
    exit();
} catch (Exception $exc) {
    echo $exc->getMessage();
    // Log the whole exception object to a file.
    // $logger->log($exc);
    exit();
}

如果您愿意,请参阅我的回答 here(“编辑”部分),我在其中发布了一个 db 适配器类。它为您处理所有数据库操作、验证和异常处理案例。

【讨论】:

    猜你喜欢
    • 2021-11-26
    相关资源
    最近更新 更多