Php 更新重复密钥时出错

Php 更新重复密钥时出错,php,mysql,Php,Mysql,你能告诉我我做错了什么吗 我有一个功能,可以在数据库中添加用户id、属性id和用户输入的答案在此之前,它可以工作。但当我添加重复密钥更新部分以更新用户答案而不是创建新答案时,它会抛出一个错误: 致命错误:未捕获错误:在第39行的……\Attributes.php中对布尔值调用成员函数execute() 在那一行我有$add_user->execute() 下面添加了插入数据库的函数。如果我删除了“重复更新”部分,它将插入数据库,并且一切正常,但我需要,如果用户已经回答了,它将更新现有部分,而不是

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

我有一个功能,可以在数据库中添加用户id、属性id和用户输入的答案在此之前,它可以工作。但当我添加重复密钥更新部分以更新用户答案而不是创建新答案时,它会抛出一个错误:

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

在那一行我有$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;
    }
}
编辑

更新代码后,我遇到了以下问题:

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

    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();
}
公共函数updateAttributes($attribute\u id,$attribute\u text){ $dbobj=新连接(); $connection=$dbobj->getConnection()


}

该错误是由准备失败引起的,因为重复密钥更新上的
子句不应包含
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)");

您正在字符串中注入变量,这违背了准备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

如果数据库服务器无法成功准备语句,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,
]);
也正如他在沟里指出的那样

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

ALTER TABLE user_answers ADD PRIMARY KEY (user_id);

连接的邮政编码
类<代码>$connection->prepare()似乎返回boolean@MehravishTemkar你在说什么?@Tschallacka更新了密码。它仍然在数据库中创建新数据,而不是更新。屏幕截图--数据库中应该只有3个数据,而不是6个,它只是每次不断添加新数据,而不是更新…@Mee好吧,现在它工作了,所以根本问题已经解决了。请将新查询添加到问题中。只需编辑它,在一行下添加新的sql语句即可。另外,您是否已将键列设置为主键?否则,数据库引擎无法知道它是主键列,并且不会更新它。在将表设置为主键列之前,您很可能必须截断该表以删除重复值。@Tschallacka无法对您的答案进行投票,但谢谢!这是主要的关键问题。爱你。@Mee现在如果答案对你有帮助,你可以对它进行投票,但如果它解决了你的问题,你可以单击复选标记接受它,你可以这样做。