通常,我想在我的一个用户上运行查询,我希望以一对一的关系存储与该用户相关联的行。所以,让我们说(这只是一个任意的例子),我有一个表跟踪用户的汽车,以及一些关于汽车的信息。每个用户可以拥有0或1辆汽车。如果用户没有汽车,则表中没有该用户的条目。
汽车表(再次,只是一个例子): id,user_id,car_make,car_model
所以,当我更新这个表时,我总是会做这样的事情(伪代码):
result = SELECT * FROM cars WHERE user_id=5
if (num_rows(result)>0){
UPDATE cars SET car_make='toyota', car_model='prius' WHERE user_id=5
}else{
INSERT INTO cars (user_id, car_make, car_model) VALUES (5, 'toyota', 'prius')
}
我怎样才能把它变成一个“原子地”工作的优雅陈述?如果在另一个进程中SELECT和UPDATE语句之间的行被删除,会发生什么?我的UPDATE语句将失败INSERT语句应该运行的地方。我觉得我需要做两个相似(但不同)的陈述来完成同样的事情!我需要的是一些声明,它将向我保证我想要的数据存在于表中,特别是当我只想要一行满足我的要求时。例如,它可能是类似的东西(当然这是完全构成的):
MAKE SURE A ROW IN cars WHERE user_id=5 IS SET WITH car_make='toyota', car_model='prius'
这样,如果user_id已经存在,它将被更新,否则将被插入。此外,如果我更改了要求,例如说每个用户可以拥有给定car_make的零个或一个汽车,那么我可以进一步指定:
MAKE SURE A ROW IN cars WHERE user_id=5 AND car_make='toyota' IS SET WITH car_model='prius'
我希望我的问题有道理!如何改进这种经常出现的基本insert-if-not-found或update-if-found操作?谢谢你的帮助!
答案 0 :(得分:17)
您可以使用“REPLACE INTO”或“INSERT… ON DUPLICATE KEY UPDATE”。我相信第二个是你想要的,但有些情况下REPLACE INTO很方便。
答案 1 :(得分:6)
来自my other Stack Overflow answer:
如果您想在一个语句中执行此操作,我建议使用INSERT ... ON DUPLICATE KEY UPDATE
语法,如下所示:
INSERT INTO table (id, someothervalue) VALUES (1, 'hi mom')
ON DUPLICATE KEY UPDATE someothervalue = 'hi mom';
如果没有具有指定键值(主键或唯一键)的现有记录,则将执行初始INSERT
语句。如果记录已存在,则执行以下UPDATE
语句(someothervalue = 3
)。
所有版本的MySQL都支持此功能。有关详细信息,请参阅MySQL Reference Manual page for INSERT ... ON DUPLICATE KEY UPDATE
答案 2 :(得分:2)
这称为UPSERT( UP 日期或 SERT )。你可以搜索一些关于它的SO问题。 See Wikipedia
编辑: MySQL 4.1+支持INSATE( INS ert或upd ATE ),这应该会让你得到同样的东西,只要你有一把主键。 MySQL Manual
答案 3 :(得分:1)
我认为切换它更容易。尝试插入,然后更新。
MySQL专门有一个子句'ON DUPLICATE KEY'
INSERT INTO cars(fields)VALUES(值)ON DUPLICATE KEY UPDATE ...
这当然要求您设置适当的唯一密钥。
答案 4 :(得分:0)
在Oracle中,您有Merge。
不知道MySql,但这个词可能会给你一些其他搜索。
答案 5 :(得分:0)
我如何使用ON DUPLICATE KEY UPDATE的示例: INSERT INTO注册表(名称,值)VALUES('“。$ key。”','“。$ val。”')ON DUPLICATE KEY UPDATE value ='“。$ val。”'“