应用程序中的标准问题是如果记录不存在则插入记录 - 如果记录存在则更新。在PRIMARY KEY
未知的情况下,通常会发出SELECT
,然后在找到记录后运行INSERT
或UPDATE
来解决此问题。
但是,我知道至少有三种方法可以将记录插入数据库,即使记录已经存在。就个人而言,如果已经存在,我宁愿删除新的插入请求,但是在某些情况下,您可能会倾向于删除数据库中的记录并使用新的插入请求。
CREATE TABLE IF NOT EXISTS `table` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`foo` int(10) unsigned NOT NULL,
`bar` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `row` (`foo`,`bar`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
以下是三种方法:
INSERT IGNORE INTO table (foo, bar) VALUES (2,3);
INSERT INTO table (foo, bar) VALUES (2,3) ON DUPLICATE KEY UPDATE;
REPLACE INTO table (foo, bar) VALUES (2,3);
在什么时候应该使用这些方法? 有人可以提供一些正确使用场景的例子吗?
答案 0 :(得分:5)
INSERT
假设您要存储日志条目,您需要记录每个事件,请使用INSERT
。
INSERT IGNORE
,如果它是创建它的当前插入,或者它已经是本强>
假设您有一个电话号码表和使用次数,您会找到一个您不确定的新电话号码,但是您希望它在那里。
您使用INSERT IGNORE
确保它在那里。
REPLACE INTO
,如果存在,则您需要使用新值,而不是存在强>
您还有另一个包含电话号码的表格,这次您会找到一个新号码和一个与之关联的名称。
您使用REPLACE INTO
查找并更新完整的记录,或只是插入新信息。
<强> INSERT INTO ... ON DUPLICATE KEY UPDATE ...
强>
请注意,不是另一种编写REPLACE INTO
的方法,只要您确定存在特定密钥,就应该使用上述内容,但如果确实存在更新列中的部分,而非所有列。
例如,如果您要存储来自某个IP的访问次数以及该用户访问过的第一个页面。
INSERT INTO visitors (ip,visits,first_page) VALUES (<ip>,1,<current_page>) ON DUPLICATE KEY visits = visits +1;
答案 1 :(得分:3)
在你的问题中,你有
INSERT INTO `table` (foo, bar) VALUES (2,3) ON DUPLICATE KEY UPDATE;
只有当行索引为UNIQUE时才能工作:
CREATE TABLE IF NOT EXISTS `table` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`foo` int(10) unsigned NOT NULL,
`bar` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `row` (`foo`,`bar`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
否则,为什么只有一个索引?
此外,ON DUPLICATE KEY
子句允许您更新非索引列。
至于REPLACE
,请注意REPLACE
实际上是DELETE
和INSERT
。