Insert into a MySQL table or update if exists
我想在数据库表中添加一行,但如果存在具有相同唯一键的行,我想更新该行。
例如,
假设唯一键是id,并且在我的数据库中有一行id = 1。 在这种情况下,我想用这些值更新该行。 通常这会产生错误。 如果我使用insert IGNORE,它将忽略错误,但它仍然不会更新。
-
SQL需要此用例的官方语法,它不会强制语法中的值重复并保留主键。
-
要获得受影响的id,请参阅MySQL ON DUPLICATE KEY - 最后一次插入ID?
-
警告:从版本5.7开始,这种方法不直接支持WHERE子句作为INSERT / UPDATE操作的一部分。 此外,UPDATE实际上计为两个单独的操作(DELETE和INSERT)...以防止出于审计目的。(Learnbit)
使用INSERT ... ON DUPLICATE KEY UPDATE
查询:
-
+1从我发现的情况来看,这种方法对于自动增量键和其他唯一键冲突的问题比REPLACE INTO少,而且效率更高。
-
很棒的答案和链接。此方法最好,因为它检查PRIMARY键,UNIQUE索引和自动增量列。所以INSERT INTO table (a,b,c) VALUES (NULL,"A", 19)仍会导致更新事件。
-
我知道你们所有人都提到这一点,但我想明确其他人。如果您插入的ID不是PRIMARY KEY或UNIQUE,那么这将不起作用。这最初并不适合我,因为我的身份证并不是唯一的。
-
我想知道为什么affected row count在成功更新(在重复键上)单行时导致2?其他人有这个结果吗? (数据正确更新:意味着只更新了一行)
-
Dimitry K--确认。在更新时,结果有时会报告影响两个查询(即使表中只有一个查询)。有时它报告0(!)受影响的行。插入始终会影响一行。我不明白为什么会这样。
-
这有点晚了,但无论如何:手册中说明ON DUPLICATE KEY UPDATE中的更新会将受影响的行增加2.如果没有实际更新,则报告0(与常规UPDATE相同)。
-
有没有办法将它与多个插入组合(使用一个INSERT语句)? MSSQL允许使用1个语句插入多达1000行,我真的需要这样做但是使用这个答案。
-
有没有办法找出运行的查询?我想将它保存在布尔值中并相应地处理。如果没有找到Duplicate key,则将insert boolean设置为true。
-
完善!谢谢!我首先在事务UPDATE中使用,如果0行影响INSERT之前看到这个!
-
如何在同一时间检查(如果不存在)两列?
-
这可以在SQL Server 2005中使用吗?
-
它有时会说2行受影响的原因是您可以判断是否执行了插入或更新。 1行受影响=插入,2行受影响=更新。 dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
-
嗯,不适合我。"'ON'附近的语法错误"..将字段设置为唯一&amp;删除/重新创建为我的<50个数据集提供相同的结果:)
-
我有几个字段,所以看起来这个方法将导致一个巨大的绑定调用(PHP / mysqli)。我将调查R??EPLACE - 这些评论标志着一些警告,但所有看起来都适合我的应用程序。
-
另请注意,您可以使用VALUES(名称)来引用您尝试插入的值,例如INSERT INTO表(id,name,age)VALUES(1,"A",19)ON DUPLICATE KEY UPDATE name = VALUES(name),age = VALUES(age)
-
@Donnie和其他人,我想使用这个查询,但我想检查是否存在针对project_id = pId和expert_id = eId的记录,然后UPDATE ml_match否则INSERT project_id,expert_id,ml_match并忽略其他列。你能写查询吗? ON DUPLICATE KEY UPDATE仅适用于主键或任何字段名称吗?
-
很好地完成了查询的灵活性,只需在插入结束时进行查询。
-
嘿,朋友,我想检查名称在数据库中可用,然后可用,然后替换年龄,否则插入记录
-
请记住"重复密钥更新"存在问题。如果由于任何原因失败,即使没有添加数据,自动完成ID仍会自动递增。因此我不使用它。我只是检查是否有当前的ID。如果我有更新,如果没有我插入的ID。
-
@Keven很棒,如果你的ID不是唯一的,那么它不是ID,不是吗? :D你可以说它在表中的出现并不是唯一的,但你不能说ID不是唯一的x)...
-
它不适用于MySQL!
-
@ ersks-这显然是一个MySQL构造。如果它不起作用,您的表模式对于您尝试的内容是错误的,或者您使用它是错误的。
-
@Donnie,工作正常。谢谢。
查看REPLACE
http://dev.mysql.com/doc/refman/5.0/en/replace.html
-
@Piontek因为这个更简短,更容易理解,没有人解释为什么"重复插入"更好。
-
它会更改记录的ID,因此可能会破坏外部引用。
-
REPLACE INTO的另一个问题是您必须为所有字段指定值...否则字段将丢失或替换为默认值。 REPLACE INTO基本上删除该行(如果存在),并插入新行。在该示例中,如果您执行'REPLACE INTO table(id,age)值(1,19),则name字段将变为null。
-
这实际上是删除整行并执行新的INSERT。
-
@mjb因此你需要拥有DELETE权限,如果你不需要它们,最好不要拥有它们。我的环境的数据库用户只有INSERT和UPDATE权限,因此REPLACE不起作用。
-
这有它的位置。
-
它不会更改记录的ID,但会删除记录,然后将其重新插入到匹配项中,MySQL将其视为违反外键。
使用批量插入时,请使用以下语法:
1 2 3 4
| INSERT INTO TABLE (id , name , age ) VALUES (1,"A", 19), (2,"B", 17), (3,"C", 22)
ON DUPLICATE KEY UPDATE
name = VALUES (name ),
... |
-
你能写出一个完整的示例批量查询吗?我不太明白你的语法。
试试这个:
希望这可以帮助。
-
实际上我不需要将新值添加到具有新ID的另一行,而是我想用这个值替换id = 1的现有值。 (据我所知,这会增加id并添加数据)
-
我不认为他想在副本上增加一个id。
-
这是一个更好的答案IMO,因为它违反了所有SQL的风格而不仅仅是MySQL
-
"违规"不是你要找的那个词:)不幸的是,现在我看到了"违规",我再也看不到实际的词了。
-
你在寻找"遍历"或"封面"吗?
-
@mwfearnley你想要想象的那个词是"超越"。只花了一年半的时间:-)
试试这个:
INSERT INTO table (id,name,age) VALUES('1','Mohammad','21') ON DUPLICATE KEY UPDATE name='Mohammad',age='21'
注意:
这里,如果id是主键,那么在每次尝试插入id='1'时首次插入id='1'后,将更新名称和年龄,之前的名称年龄将发生变化。
-
我想在不使用id的情况下工作。你试过没有主键吗?
-
@ersks看到了这个问题。用户询问何时有唯一键
-
我明白了,但我正试图解决我的问题,其中只有这些值才知道。所以,在这种情况下,我写了上面的评论希望正确的解决方案。
1 2 3 4 5
| INSERT IGNORE INTO table (id , name , age ) VALUES (1,"A", 19);
INSERT INTO TABLE (id , name , age ) VALUES(1,"A", 19) ON DUPLICATE KEY UPDATE NAME ="A", AGE = 19;
REPLACE INTO table (id , name , age ) VALUES(1,"A", 19); |
所有这些解决方案都适用于您的问题。
如果您想详细了解这些声明,请访问此链接
-
链接文档中未记录REPLACE。
-
sql查询充满了错别字,你的例??子将无法正常工作。它是INSERT INTO TABLE(不是INTO TABLE)和ON DUPLICATE KEY UPDATE(不是ON DUPLICATE UPDATE SET)。不确定是谁支持这一点
-
抱歉打字错误。谢谢你纠正我
使用SQLite时:
前提是id是主键。否则它只是插入另一行。请参阅INSERT(SQLite)。
-
replace into的作用正是"插入或在现有时更新"。 @猫头鹰
-
+1(1/3)我发现这适合我的情况 - 我需要用一个唯一的密钥替换现有的行,否则就添加该行。这里最简单的解决方案。
-
(2 of 3)我的查询:CREATE TRIGGER worklog_update AFTER INSERT ON worklog FOR EACH ROW REPLACE INTO support_time_monthly_hours ( ProjectID, monthTotalTime, Year, Month ) SELECT jiraissue.PROJECT, SUM(worklog.timeworked), YEAR(CURRENT_DATE()), MONTH(CURRENT_DATE()) FROM worklog, jiraissue WHERE worklog.issueid = jiraissue.ID AND jiraissue.PROJECT = (SELECT PROJECT FROM jiraissue WHERE NEW.issueid = jiraissue.ID ) AND worklog.startdate BETWEEN DATE_FORMAT(NOW() ,'%Y-%m-01 00:00:00') AND NOW();
-
(3的3)相关问题/答案stackoverflow.com/questions/41767517/…
-
mysql中的这个问题是,如果没有提供,则replace将删除其他值。但是@ fabiano-souza解决方案更合适
仅仅因为我在这里寻找这个解决方案,但是要从另一个结构相同的表(在我的网站测试数据库中更新到实时数据库)进行更新:
如其他地方所述,只需要在ON DUPLICATE KEY UPDATE之后包含要更新的列。
无需列出INSERT或SELECT中的列,但我同意这可能是更好的做法。
在我的情况下,我创建了下面的查询,但在第一个查询中,如果id 1已经存在并且age已经存在,那么如果你创建第一个查询而没有age而不是age的值将是
为避免上述问题创建如下所示的查询
它可以帮助你......
-
有谁知道为什么我们必须两次分配值?为什么MySQL不允许我们在ON DUPLICATE KEY UPDATE结束查询而不复制所有赋值语句?一些数据库表有很多列,这似乎是多余的/无偿的。我理解为什么我们可以选择备用作业,但为什么不选择省略它们呢?只是好奇,如果有人知道。
另外不要忘记关注唯一键约束。