› MySQL 5.5 Community Server
› MySQL 5.6 Community Server
› Percona Configuration Wizard
› XtraBackup 搭建主从复制
Great Sites on MySQL
› Percona
› MySQL Performance Blog
› Severalnines
推荐管理工具
› Sequel Pro
› phpMyAdmin
推荐书目
› MySQL Cookbook
MySQL 相关项目
› MariaDB
› Drizzle
参考文档
› http://mysql-python.sourceforge.net/MySQLdb.html
uti6770werty
V2EX  ›  MySQL

求助 SQL 语句,关于 INSERT INTO xxx ON DUPLICATE KEY UPDATE...

  •  
  •   uti6770werty · Feb 17, 2022 · 4323 views
    This topic created in 1681 days ago, the information mentioned may be changed or developed.

    INSERT INTO mcrun (starttime,loop,chckport,mcid,UpdateTime) VALUES ('2022-02-15 09:20:11','9','R','217',NOW()) ON DUPLICATE KEY UPDATE xxx

    mcrun 表只有mcid约束唯一的键
    现在 INSERT INTO '217'这个语句,
    有可能表里已经有 217 数据了,
    想完成这个事情,的 UPDATE 做一些判断修改表的方法应该如何实现?

    1 、如果指定的starttime,loop这两个在表的数据,和新插入有不同,单一个值有变化,也算条件成立,就更新最新的值,并把 UpdateTime 修改成 NOW()
    2 、如果指定的starttime,loop这两个在表的数据,和新插入的一样,什么都不用动
    3 、chckport的字段,不用理会

    能不能单条语句完成?

    如果一条语句实在办不到,自己能想到的是,解除约束健设置,直接新加入地写入,周期地删除重复 mcid ,只保留最新的 mcid 条目。。。,效率低,查询又要增加 order by UpdateTime LIMIT 1 ,很麻烦。。。

    谢谢各位大佬能解答这个问题,谢谢!

    16 replies  •  2022-02-19 15:25:32 +08:00
    zhoudaiyu
        1
    zhoudaiyu  
       Feb 17, 2022 via iPhone
    这个 SQL 默认逻辑不就是这样吗?如果 uniquekey 不存在,插入本次的数据,如果存在则更新除了 uniquekey 以外的数据
    uti6770werty
        2
    uti6770werty  
    OP
       Feb 17, 2022
    @zhoudaiyu [如果存在则更新除了 uniquekey 以外的数据] ,这个 SQL 是会把 UpdateTime 也更新过去的,数据没有变化的话
    uti6770werty
        3
    uti6770werty  
    OP
       Feb 17, 2022
    也就是想把逻辑判断也做在 SQL 语句里
    littlewing
        4
    littlewing  
       Feb 17, 2022
    update 后面可以跟 col_name = 'value' 的
    goodSleep
        5
    goodSleep  
       Feb 18, 2022 via Android
    update 后跟 case when ,看看下面的例子 能解决问题么
    https://stackoverflow.com/questions/24000685/insert-on-duplicate-key-update-if
    MarsBar
        6
    MarsBar  
       Feb 18, 2022
    假设你说的是 postgresql
    那么: https://www.postgresqltutorial.com/postgresql-upsert/
    你可以用:
    DO UPDATE SET column_1 = value_1, .. WHERE condition
    xaplux
        7
    xaplux  
       Feb 18, 2022
    试试把 UpdateTime 设置为有变动时自动更新,不要显示的传入
    mysql 可以这样:
    `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

    你的 sql 语句改为:
    NSERT INTO mcrun (starttime,loop,chckport,mcid) VALUES ('2022-02-15 09:20:11','9','R','217') ON DUPLICATE KEY UPDATE xxx
    xaplux
        8
    xaplux  
       Feb 18, 2022
    仔细看了一下你的需求,我上面说的也实现不了,建议你还是乖乖的先查出来,再更新吧
    dqzcwxb
        9
    dqzcwxb  
       Feb 18, 2022
    不建议使用 ON DUPLICATE,会导致自增主键不连续因为它的是先尝试 insert 发现唯一索引冲突再 delete 数据再 insert

    如果你的业务大部分情况下是 update,那么建议直接 update 再判断返回值是否为 1,如果为 1 则说明更新成功不用再处理如果为 0 则说明数据不存在或者 update 前后数据一致,那么此时需要 select 数据然后判断是 insert 还是不需要处理,记得 insert 的时候加锁或者忽略索引冲突异常即可
    jimmzhou
        10
    jimmzhou  
       Feb 18, 2022
    不知道楼主用啥语言 啥框架 golang 中 使用 gorm 有 Upsert 操作 可以指定更新需要修改的字段
    uti6770werty
        11
    uti6770werty  
    OP
       Feb 18, 2022
    谢谢各位,我没有用 ORM 的方式去与数据库交互,至于自增 id ,其实也不需要去考虑的,因为数据的发展永远到不了极限。。。

    我琢磨着试试写:
    ```
    INSERT INTO mcrun (starttime,loop,chckport,mcid,UpdateTime) VALUES ('2022-02-15 09:20:11','9','R','217',NOW())
    ON DUPLICATE KEY UPDATE `starttime`=IF(`starttime`<>'2022-02-22 22:22:22','2022-02-22 22:22:22',`starttime`),
    `loop`=IF((`loop`<>'9' OR `loop` IS NULL),'9',`loop`),
    `UpdateTime`=IF(`starttime`<>'2022-02-22 22:22:22' OR `loop`<>'9',NOW(),`UpdateTime`);
    ```

    1 、starttime 和 loop 都能被逻辑识别和修改成功,
    2 、主要是 UpdateTime ,好像条件没成立,也会被更新,是不是 SQL 语句做不了这么的逻辑判断?
    onhao
        12
    onhao  
       Feb 18, 2022
    不知 OP 敢不敢用触发器 例如: https://wuhao.pw/archives/268/
    把你的 1 ,2 ,3 写到触发器里去,不就完美了?
    uti6770werty
        13
    uti6770werty  
    OP
       Feb 18, 2022
    我的情况是,触发器过于维护复杂,安置的时候很爽,但后面有变动就算有文档都变得困难。。。

    最后,
    INSERT INTO mcrun (starttime,loop,chckport,mcid,UpdateTime) VALUES ('2022-02-15 09:20:11','9','R','217',NOW())
    ON DUPLICATE KEY UPDATE
    `UpdateTime`=IF(`starttime`<>'2022-02-22 22:22:22',NOW(),`UpdateTime`),
    `UpdateTime`=IF(`loop`<>'9' OR `loop` IS NULL,NOW(),`UpdateTime`),
    `starttime`=IF(`starttime`<>'2022-02-22 22:22:22','2022-02-22 22:22:22',`starttime`),
    `loop`=IF(`loop`<>'9' OR `loop` IS NULL),'9',`loop`);

    算研究出来了,
    逐个目标拆开写,细写,
    我想的是,SET 的顺序优先考虑 UpdateTime 处理了,再去判断真正的数值,
    这个逻辑在这个案例里够用,目前妥妥的正常,
    不知道会不会有什么幺蛾子没预料会发生的。。。。
    markgor
        14
    markgor  
       Feb 18, 2022
    @onhao #12
    触发器 一不小心就家毁人亡了......
    onhao
        15
    onhao  
       Feb 19, 2022
    @markgor 哈哈,不至于 @uti6770werty 是把,触发器这条路,也是条路,选择合适的在于自己,按需使用,其实没有必要把触发器想成洪水猛兽。
    markgor
        16
    markgor  
       Feb 19, 2022
    @onhao #15
    触发器,联合索引, 修改数据时一不小心导致另一张表也改变,但是自己不知道。后来自己测试时才发现异常,还好是在测试环境中。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2634 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 38ms · UTC 09:02 · PVG 17:02 · LAX 02:02 · JFK 05:02
    ♥ Do have faith in what you're doing.