你能告诉我我做错了吗?
我有一个功能,可以在数据库中添加users_id,attribute_id和用户输入的答案。 直到它起作用。但是,当我添加ON DUPLICATE KEY UPDATE部分来更新用户答案而不创建新的答案时,会抛出错误:
致命错误:未被捕获的错误:在第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;
}
}
编辑
更新代码后,我遇到了这个问题:
下面添加了插入数据库的函数。如果我删除“重复更新”部分,它将插入数据库中,并且一切正常,但是我需要,如果用户已经回答过,它会更新现有文件,而不会在数据库中插入新数据:
公共函数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 (?, ?, ?) 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();
}
答案 0 :(得分:1)
由于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)");
答案 1 :(得分: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,
]);
现在,对于重复密钥问题。数据库如何识别主键是哪个键?您现在已经定义了两个键。这就是为什么您必须定义主键的原因。在执行此语句之前,您可能必须截断表或删除重复项。
ALTER TABLE user_answers ADD PRIMARY KEY (user_id);