首页 > 解决方案 > 插入或更新,但不确定我是否可以进行重复的密钥更新

问题描述

创建一个书签系统。用户可以为要关注的玩家添加书签或取消添加书签。从表面上看,我认为重复的密钥更新可以与 playerID 一起使用。但是,一个玩家可能有几个用户为他添加书签。

所以它必须将 playerID 与 userID 配对。如果该对不存在,则插入。如果该对确实存在,请更新。

以下是我对重复密钥更新的内容。我将如何检查一对两列?康卡特?

$query = "INSERT INTO a_player_bookmark (playerID,bookmark,userID,username)
                        VALUES ('". $pid ."','". $bookmark ."','". $userID ."','". $user ."')
                        ON DUPLICATE KEY
                        UPDATE bookmark = '". $bookmark ."'

                        ";

标签: mysqlinsert-updateon-duplicate-key

解决方案


对,所以通过外键关联每一列(为了完整起见),然后在2 列上创建一个唯一键,包括playerID(follower) 和userID(followed)。然后你可以有a -> b, 和b -> a,但是再次添加会导致重复键错误。这允许您使用ON DUPLICATE KEY UPDATE follower=follower跳过插入或bookmark = VALUES(bookmark)更新书签值。

为简洁起见,我还重命名了您的表格bookmarks

-- the sql query (plain text / string)
INSERT INTO bookmarks (playerID, bookmark, userID, username)
    VALUES (:playerID, :bookmark, :userID, :username)
ON DUPLICATE KEY UPDATE bookmark = VALUES(bookmark)

现在在 PHP 中,我已经演示了使用 PDO 运行准备好的语句的基本概念。如果您不愿意执行 PDO,那么您可以相应地连接到查询中(自己替换占位符),但我强烈反对这样做。

//within php
$con = /* a PDO connection reference, see PDO docs for creating one */;
$query = /* our earlier statement, in string form */;
$stmt = con->prepare($query); //creates a PreparedStatement
//bind our values to the placeholders in the sql statement
$stmt->bindValue(':playerID', $pid, PDO::PARAM_INT);
$stmt->bindValue(':bookmark', $bookmark, PDO::PARAM_STR);
$stmt->bindValue(':userID', $userID, PDO::PARAM_STR);
$stmt->bindValue(':username', $user, PDO::PARAM_STR);
$stmt->execute(); //run the query
$updated = $stmt->rowCount(); //number of updated rows

展望未来,我将username作为一列删除(似乎多余,为什么不直接引用 users 表来获取名称?),然后根据我的目的,bookmark我什至可能会放弃它。

但在此之前,您需要确保正确的钥匙在您的桌子上。

-- I suggest removing any existing constraints beforehand
-- Relate playerID to the users table
ALTER TABLE bookmarks ADD CONSTRAINT `FK_follower` FOREIGN KEY (`playerID`) REFERENCES `users` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
-- Relate userID to the users table
ALTER TABLE bookmarks ADD CONSTRAINT `FK_followed` FOREIGN KEY (`userID`) REFERENCES `users` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
-- Relate username to the users table, if you decide to keep it
ALTER TABLE bookmarks ADD CONSTRAINT `FK_followed_name` FOREIGN KEY (`username`) REFERENCES `users` (`username`) ON UPDATE CASCADE ON DELETE CASCADE
-- Add your UNIQUE KEY for the two columns defining the relationship, aka a composite key
ALTER TABLE bookmarks ADD UNIQUE INDEX `following` (`playerID`, `userID`)

推荐阅读