On Duplicate Key Update与insert相同

Roy*_*Roy 147 mysql on-duplicate-key

我已经四处搜索,但没有找到是否可能.

我有这个MySQL查询:

INSERT INTO table (id,a,b,c,d,e,f,g) VALUES (1,2,3,4,5,6,7,8)
Run Code Online (Sandbox Code Playgroud)

字段ID具有"唯一索引",因此不能有两个.现在,如果数据库中已存在相同的ID,我想更新它.但是我真的必须再次指定所有这些字段,例如:

INSERT INTO table (id,a,b,c,d,e,f,g) VALUES (1,2,3,4,5,6,7,8) 
ON DUPLICATE KEY UPDATE a=2,b=3,c=4,d=5,e=6,f=7,g=8
Run Code Online (Sandbox Code Playgroud)

要么:

INSERT INTO table (id,a,b,c,d,e,f,g) VALUES (1,2,3,4,5,6,7,8) 
ON DUPLICATE KEY UPDATE a=VALUES(a),b=VALUES(b),c=VALUES(c),d=VALUES(d),e=VALUES(e),f=VALUES(f),g=VALUES(g)
Run Code Online (Sandbox Code Playgroud)

我已经在插入中指定了所有内容......

一个额外的说明,我想使用工作来获取ID!

id=LAST_INSERT_ID(id)
Run Code Online (Sandbox Code Playgroud)

我希望有人能告诉我最有效的方法是什么.

hjp*_*r92 75

UPDATE给出该语句,以便可以将旧字段更新为新值.如果您的旧值与新值相同,为什么在任何情况下都需要更新它?

例如.如果你的列ag已经被设置为28; 没有必要重新更新它.

或者,您可以使用:

INSERT INTO table (id,a,b,c,d,e,f,g)
VALUES (1,2,3,4,5,6,7,8) 
ON DUPLICATE KEY
    UPDATE a=a, b=b, c=c, d=d, e=e, f=f, g=g;
Run Code Online (Sandbox Code Playgroud)

要获得idLAST_INSERT_ID; 您需要指定您正在使用的后端应用程序.

对于LuaSQL,conn:getlastautoid()获取值.

  • 如果表`tbl`已经有行(1,10)那么:`INSERT INTO tbl(id,a)VALUES(1,2)ON DUPLICATE KEY UPDATE a = VALUES(a)`将设置a =**2**.`INSERT INTO tbl(id,a)VALUES(1,2)ON DUPLICATE KEY UPDATE a = a`将设置a =**10** (44认同)
  • 这仅仅是为了这个例子.在现实生活中的查询中存在差异.我的问题很简单:如果它们与插入中的相同,我是否真的需要指定所有字段(以及我的第一个示例中的值)?我只想插入全部或者如果有唯一值匹配:全部更新. (6认同)
  • 为什么大家都点赞?这是行不通的。正如 @Bùi Việt Thành 指出的那样,使用 `a=a` 不会更新任何内容。(原始问题中的查询实际上也没有更新任何内容,但更新似乎是OP的意图。) (5认同)
  • 是的,在这种情况下,您确实需要更新所有这些内容. (2认同)

Dan*_*ack 38

SQL的MySQL特定扩展可能是你想要的 - REPLACE INTO

但是它与'ON DUPLICATE UPDATE'的工作原理完全不同

  1. 它删除与新行冲突的旧行,然后插入新行.只要你没有表上的主键就可以了,但如果你这样做,那么如果你有任何其他表引用那个主键

  2. 您不能引用旧行中的值,因此您无法执行相应的操作

    INSERT INTO mytable (id, a, b, c) values ( 1, 2, 3, 4) 
    ON DUPLICATE KEY UPDATE
    id=1, a=2, b=3, c=c + 1;
    
    Run Code Online (Sandbox Code Playgroud)

我想用这个工作来获取ID!

这应该工作 - 只要你的主键是自动递增的,last_insert_id()应该有正确的值.

但是正如我所说,如果您实际在其他表中使用该主键,则REPLACE INTO可能无法接受,因为它会删除通过唯一键冲突的旧行.

之前有人建议您可以通过以下方式减少一些输入:

INSERT INTO `tableName` (`a`,`b`,`c`) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE `a`=VALUES(`a`), `b`=VALUES(`b`), `c`=VALUES(`c`);
Run Code Online (Sandbox Code Playgroud)

  • 正如前面的评论提到的,REPLACE INTO 删除并重新创建该行。因此,如果您有外键,则约束将失败,因此 REPLACE INTO 将失败。你最好的最好的是使用 VALUES() 进行重复密钥更新 (2认同)

小智 22

这是您的问题的解决方案:

我试图解决像你这样的问题,我想建议从简单的方面进行测试.

请遵循以下步骤:学习简单的解决方案.

步骤1:使用此SQL查询创建表模式:

CREATE TABLE IF NOT EXISTS `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(30) NOT NULL,
  `password` varchar(32) NOT NULL,
  `status` tinyint(1) DEFAULT '0',
  PRIMARY KEY (`id`),
  UNIQUE KEY `no_duplicate` (`username`,`password`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;
Run Code Online (Sandbox Code Playgroud)

包含数据的表<code> user </ code>

步骤2:使用以下SQL Query 创建两列索引以防止重复数据:

ALTER TABLE `user` ADD INDEX no_duplicate (`username`, `password`);
Run Code Online (Sandbox Code Playgroud)

或者,从GUI创建两列索引,如下所示: 从GUI创建索引 选择列以创建索引 表<code> user </ code>的索引

步骤3:如果存在则更新,如果不使用以下查询则插入:

INSERT INTO `user`(`username`, `password`) VALUES ('ersks','Nepal') ON DUPLICATE KEY UPDATE `username`='master',`password`='Nepal';

INSERT INTO `user`(`username`, `password`) VALUES ('master','Nepal') ON DUPLICATE KEY UPDATE `username`='ersks',`password`='Nepal';
Run Code Online (Sandbox Code Playgroud)

运行上面的查询后,表<code> user </ code>

  • 仅供参考,以纯文本形式存储密码是一个糟糕的主意,就像试图在数据库级别防止重复密码一样。 (2认同)

Roy*_*Roy 21

没有其他办法,我必须指明一切两次.第一个是插入,第二个是更新案例.

  • 这是不正确的,不应该是接受的答案.@Danack的答案是正确的答案. (8认同)
  • 您应该重新阅读问题@WayneWorkman,这是正确的答案。 (4认同)

Chr*_*ris 7

如果您能够使用脚本语言来准备SQL查询,则可以使用SET而不是使用field = value对(a,b,c) VALUES(a,b,c).

PHP的一个例子:

$pairs = "a=$a,b=$b,c=$c";
$query = "INSERT INTO $table SET $pairs ON DUPLICATE KEY UPDATE $pairs";
Run Code Online (Sandbox Code Playgroud)

示例表:

CREATE TABLE IF NOT EXISTS `tester` (
  `a` int(11) NOT NULL,
  `b` varchar(50) NOT NULL,
  `c` text NOT NULL,
  UNIQUE KEY `a` (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
Run Code Online (Sandbox Code Playgroud)

  • 您应该使用您的值转义您的值或执行准备好的语句. (3认同)

小智 6

我知道已经晚了,但我希望有人能从这个答案中得到帮助

INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6)
ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
Run Code Online (Sandbox Code Playgroud)

您可以在此处阅读以下教程:

https://mariadb.com/kb/en/library/insert-on-duplicate-key-update/

http://www.mysqltutorial.org/mysql-insert-or-update-on-duplicate-key-update/


cod*_*nja 5

您可能要考虑使用REPLACE INTO的语法,但被警告,在重复的主键/唯一键,它DELETES行和INSERTS一个新的。

您无需重新指定所有字段。但是,您应该考虑可能的性能降低(取决于您的表设计)。

注意事项:

  • 如果您有AUTO_INCREMENT主键,它将被赋予一个新的主键
  • 索引可能需要更新