数据库upsert实现

1、mysql

使用方法:

       假设name是主键,则name不存在就插入VALUES后面的值,否则将对应的addr修改为test

INSERT INTO user (name, age, addr)
VALUES
('test',20, 'here')
ON DUPLICATE KEY UPDATE
addr = 'test';

 除了上述用法,在使用中还需要注意一些以下几点:

1.  user表的部分列如果有默认值,则可以省略,类似insert语法

2.  默认优先判断是否需要update,找不到再insert所有值。

   判读update行以主键列优先,unique列次之。主键是auto时,则values后面可忽略,从而实现以unique为准。

3.  在主键为auto时,多个unique以建表中列顺序选择,如下:

假设表有主键A非auto,unique B, unique C:

  • 假设分别匹配到3行,每行对应A,B,C,则以主键列执行update
  • 假设A找不到,B,C分别匹配到两行,则以B,C列在建表中顺序选取一行,执行update
  • 若A找不到,B找到,C找不到,则那行执行update update行为:update违反unique约束等依然会返回err
  • 若A,B,C都找不到,执行insert

2、pg/sqlite3

使用方法:

INSERT INTO test_index(_id, name, age, addr_test)
VALUES('c', 'a', '1', 'b')
ON CONFLICT(_id) DO UPDATE SET
age=5
  1. 语法检测:
    values后面必须指明所有无默认值且不为NULL的字段或者非auto的列
    conflict明确指明要采用的某一个unique列,某一个unique组合列,主键
  2. 优先查找update
    根据对应conflict指定的unique列如果匹配上,一定只有一列,update
    update行为:update违反unique约束等依然会返回err
  3. insert
    根据对应conflict指定的unique列如果没有匹配上,insert
    insert只读取values后值,不会更新update的操作

3、mongo

语法:

db.collection.updateOne(
   <filter>,
   <update>,
   {
     upsert: <boolean>,
     writeConcern: <document>,
     collation: <document>,
     arrayFilters: [ <filterdocument1>, ... ],
     hint:  <document|string>        // Available starting in MongoDB 4.2.1
   }

使用方法

db.getCollection("test_index").updateOne(
{"_id":"3"},
{ $set: {"i_d" : "3", "age" : 3, "name" : "c", "addr_test":"c" } },
{ upsert: true }
);

1. 语法检测
filter和update 部分不能同时设置_id字段
2. 优先update
update部分,各列可以随意组合,之间是AND操作,匹配到多行时,选择其中一行update
3. insert值是 filter和update 部分的列取并集,都有的部分以update部分为准
4. 问题:mongo没法对同一列insert和update不同的值,有解决方案是要到4.2以后,设置条件判断

5. setOnInsert可以解决insert值问题

db.getCollection("meta").update(
   {"client_id":"test"},
   { $set: {"name" : "test2", "state":NumberInt(1) },
     $setOnInsert:{"_id":"123","client_id":"test1"} },
   { upsert: true }
);

setOnInsert 只在是insert时更新,相同值client_id以setOnInsert为准

猜你喜欢

转载自blog.csdn.net/yshhuan/article/details/111195666