【问题标题】:INSERT or UPDATE, but not sure I can have duplicate key update插入或更新,但不确定我是否可以进行重复的密钥更新
【发布时间】:2020-04-13 02:49:15
【问题描述】:

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

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

以下是我为重复密钥更新所做的。我将如何检查一对两列?连接?

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

                        ";

【问题讨论】:

  • 可能最好保留基础数据表的两个独立(和索引)表视图,这样您就可以轻松查看您关注的人和关注您的人。也就是说,您需要在follower -> followed 的数据表中建立关联,这是严格单向的,因此您可以将两列的复合唯一键放在一起。然后你就可以使用 upsert 了。
  • 我没有完全理解你所说的。如果存在呢?
  • insert ... on duplicate key update 是一个 upsert(更新插入)。您是在问如果该值已经在表中怎么办?那将是唯一密钥的好处。此外,即使您刚开始,我也建议您使用 PDO 并了解准备好的语句,出于安全原因,将您的值连接到查询中也是一个很大的禁忌。
  • playerID 和 userID 是其他数据表中的唯一键,我有这个书签表,我在其中关联关注者并关注。我需要查询帮助来检查关系是否存在以确定我是否需要插入或更新。

标签: mysql insert-update on-duplicate-key


【解决方案1】:

对,所以通过外键关联每一列(为了完整起见),然后在 2 列上创建一个唯一键,playerID(跟随者)和userID(紧随其后)。然后你可以有a -> bb -> 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 作为一列删除(似乎多余,为什么不直接引用用户表来获取名称?),然后根据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`)

【讨论】:

  • 成功了!我正在学习这些东西,所以创建索引对我来说是一个新概念。 Thank youusername 对我来说更像是一种视觉效果。没用过。
猜你喜欢
  • 2014-10-31
  • 2011-09-08
  • 1970-01-01
  • 1970-01-01
  • 2012-11-17
  • 2017-10-17
  • 2015-12-11
  • 1970-01-01
  • 2021-11-11
相关资源
最近更新 更多