【问题标题】:error with update on duplicate key重复键更新错误
【发布时间】:2018-08-02 18:38:07
【问题描述】:

你能告诉我我做错了什么吗?

我有一个在数据库中添加 users_id、attribute_id 和用户输入答案的函数。 在那之前它可以工作。但是,当我添加 ON DUPLICATE KEY UPDATE 部分以更新用户答案而不是创建新答案时,它会引发错误:

致命错误:未捕获的错误:调用布尔值中的成员函数 execute() ......\Attributes.php 第 39 行

在那一行我有 $add_user->execute();

下面添加了插入数据库的功能。如果我删除“重复更新”部分,它将插入数据库并且一切正常,但我需要如果用户已经回答它,它会更新现有的而不是在数据库中插入新数据:

    public function updateAttributes($attribute_id, $attribute_text) {
    $dbobj = new Connection();
    $connection = $dbobj->getConnection();

    $user_id = $_SESSION['id'];
    $_attribute_id = mysqli_real_escape_string($connection, $attribute_id);
    $attribute = mysqli_real_escape_string($connection, $attribute_text);

    $add_user = $connection->prepare("INSERT into user_answers(user_id, attribute_id, answer) VALUES ('$user_id', '$_attribute_id', '$attribute') ON DUPLICATE KEY UPDATE answer = VALUES(answer) WHERE user_id = VALUES(user_id) AND attribute_id =  VALUES(attribute_id)");
    //$add_user->bind_param('iis', $user_id, $_attribute_id, $attribute);
    // ON DUPLICATE KEY UPDATE user_answer = VALUES(answer) WHERE user_id = VALUES(user_id) AND attribute_id =  VALUES(attribute_id)

    $add_user->execute();
    $add_user->close();
    $connection->close();
}

如果需要,这里是 sql 代码。包含两个外键和答案,存储用户输入的答案:

CREATE TABLE IF NOT EXISTS `user_answers` (
  `user_id` int(11) DEFAULT NULL,
  `attribute_id` int(11) DEFAULT NULL,
  `answer` varchar(50) DEFAULT NULL,
  KEY `user_id` (`user_id`),
  KEY `attribute_id` (`attribute_id`),
  CONSTRAINT `attribute_id` FOREIGN KEY (`attribute_id`) REFERENCES `attributes` (`id`),
  CONSTRAINT `user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

更新:添加连接类:

class Connection {
    public function getConnection(){
        $conn = mysqli_connect("localhost","root","","dbname") or die("Couldn't connect");
        $conn->query("SET NAMES utf8");
        return $conn;
    }
}

编辑

更新代码后我遇到了这个问题:

下面添加了插入数据库的功能。如果我删除“重复更新”部分,它将插入数据库并且一切正常,但我需要如果用户已经回答它,它会更新现有的而不是在数据库中插入新数据:

公共函数 updateAttributes($attribute_id, $attribute_text) { $dbobj = 新连接(); $connection = $dbobj->getConnection();

$user_id = $_SESSION['id'];
$_attribute_id = mysqli_real_escape_string($connection, $attribute_id);
$attribute = mysqli_real_escape_string($connection, $attribute_text);

$add_user = $connection->prepare("INSERT into user_answers(user_id, attribute_id, answer) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE answer = VALUES(answer)");
$add_user->bind_param('iis', $user_id, $_attribute_id, $attribute);

$add_user->execute();
$add_user->close();
$connection->close();

}

【问题讨论】:

  • Connection 类的邮政编码...$connection->prepare() 似乎返回布尔值

标签: php mysql


【解决方案1】:

您在字符串中注入变量,破坏了准备 SQL 语句的目的...您让您的应用程序为 SQL 注入攻击敞开大门。

$add_user = $connection->prepare("INSERT into user_answers(user_id, attribute_id, answer)
                                  VALUES ('$user_id', '$_attribute_id', '$attribute') 
                                        --^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- this is is plain wrong
                                  ON DUPLICATE KEY UPDATE answer = VALUES(answer)  
                                  WHERE user_id = VALUES(user_id) AND attribute_id =  VALUES(attribute_id)");

准备可能失败,导​​致它返回false

http://php.net/manual/en/pdo.prepare.php

如果数据库服务器无法成功准备语句,PDO::prepare() 将返回 FALSE 或发出 PDOException(取决于错误处理)。

请按你应该的方式准备。

$add_user = $connection->prepare("INSERT into user_answers(user_id, attribute_id, answer) VALUES (:user_id, :attribute_id, :attribute) ON DUPLICATE KEY UPDATE answer = VALUES(answer) WHERE user_id = VALUES(user_id) AND attribute_id =  VALUES(attribute_id)");
// Inject the variables you want in the prepared statement.

$result = $add_user->execute([
   ':user_id' => $user_id,
   ':attribute_id' => $_attribute_id,
   ':attribute' => $attribute,
]);

也正如Nick 在他的answer 中指出的那样,抛弃哪里。

现在,针对重复键问题。您的数据库如何辨别哪个键是您的主键?您现在定义了两个键。这就是为什么你必须定义一个主键。在执行此语句之前,您可能必须截断表或删除重复项。

ALTER TABLE user_answers ADD PRIMARY KEY (user_id);

【讨论】:

  • @MehravishTemkar 你在说什么?
  • @Tschallacka 更新了代码。它仍然在数据库中创建新数据而不是更新。屏幕截图 - prntscr.com/kdqz3j - 数据库中应该只有 3 个数据而不是 6 个,它只是每次都不断添加新数据而不是更新......
  • @Mee 好吧,现在它可以工作了,所以根本问题是固定的。请将您的新查询添加到您的问题中。只需编辑它,在新的 sql 准备语句下添加一行。另外,您是否将键列设置为主键?否则数据库引擎无法知道它是主键列并且不会更新它。您很可能必须先截断表以删除重复值,然后才能将其设置为主键列。
  • @Tschallacka 不能赞成您的回答,但谢谢!这是主要的关键问题。爱你。
  • @Mee And I love you too random citizen! 现在,如果答案对您有帮助,您可以投票给您还没有权限的问题,但如果它解决了您的问题,您可以单击复选标记接受它,这你可以的。
【解决方案2】:

该错误是由于准备失败导致的,因为ON DUPLICATE KEY UPDATE 子句不应该有WHERE 子句。要更新的行已经由要插入的数据与现有键匹配这一事实定义,因此WHERE 子句是多余的。尝试将您的代码更改为:

$add_user = $connection->prepare("INSERT into user_answers(user_id, attribute_id, answer) VALUES ('$user_id', '$_attribute_id', '$attribute') ON DUPLICATE KEY UPDATE answer = VALUES(answer)");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-21
    • 1970-01-01
    • 2018-07-04
    • 2014-10-07
    • 2016-04-23
    • 1970-01-01
    • 1970-01-01
    • 2011-08-06
    相关资源
    最近更新 更多