【问题标题】:Atomic update and backup ON DUPLICATE KEY insert else - golang sql statement原子更新和备份 ON DUPLICATE KEY 插入 else - golang sql 语句
【发布时间】:2018-11-20 10:01:59
【问题描述】:

结合两个语句(INSERT 或(BACKUP 和 UPDATE))并在 golang 中以原子方式执行它们的最佳方法是什么?

我发现了这个类似的问题: https://codereview.stackexchange.com/questions/186909/query-select-and-insert-if-not-exists?newreg=067063956a834327883542c3171a22d4

但那里的解决方案不满足以下要求中的 2 个:

  1. 对 DUPLICATE KEY 上的值执行备份,
  2. 使用标准 SQL
  3. 不使用存储过程,但
  4. 保持原子性。

【问题讨论】:

    标签: mysql sql go


    【解决方案1】:

    这更像是一个 SQL 问题/答案,而不是 Go 特定的,因此可能的解决方案是基于 SQL 的。

    可能的解决方案:

    (1) 替换成

    REPLACE INTO books
        (id, title, author, year_published)
    VALUES
        (1, 'Green Eggs and Ham', 'Dr. Seuss', 1960);
    

    这将覆盖现有记录。适用于唯一约束。虽然当找到匹配的记录时,它将被删除,因此它可能是不想要的行为。

    (2) 插入忽略

    INSERT IGNORE INTO books
        (id, title, author, year_published)
    VALUES
        (1, 'Green Eggs and Ham', 'Dr. Seuss', 1960);
    

    如果记录不存在,这将添加。适用于唯一约束。

    来自手册:

    如果您使用 IGNORE 修饰符,则在执行 INSERT 语句被忽略。例如,如果没有 IGNORE,那么一行 复制表中现有的 UNIQUE 索引或 PRIMARY KEY 值 导致重复键错误并且语句被中止。和 IGNORE,该行被丢弃并且不发生错误。忽略的错误可能 而是生成警告,尽管重复键错误不会。

    (3) 插入 ... 在重复密钥更新时

    INSERT INTO books
        (id, title, author, year_published)
    VALUES
        (1, 'Green Eggs and Ham', 'Dr. Seuss', 1960);
    ON DUPLICATE KEY UPDATE
        title = 'No Green Eggs and Ham';
    

    如果插入失败,来自ON DUPLICATE KEY 的值将用于生成更新语句。

    要进行备份,请创建一个历史表(具有相同结构但修改了列以获取更改日期的表)并执行INSERT ... SELECT。要成为原子,您可能需要使用具有正确锁定策略的事务 - 不确定如何为 MySQL 正确设置。

    参考:

    【讨论】:

    • thx 可能是我所要求的是不可能的,但我想从 sql 语句中对重复键错误做出反应,不仅更新行而且将旧值复制到备份表。
    • 这就是为什么只有 (3) 接近成为答案,但违反了标准 sql 要求。显然,对于标准 sql 规范,没有正确规划数据库操作,因为 MySQL 和 Postgres 针对这种常见情况有不同的解决方案:ON DUPLICATE KEY 和 UPSERT
    • ok,根据stackoverflow.com/questions/3884344/… 存储过程是实现此目的的唯一方法。
    猜你喜欢
    • 2014-05-07
    • 2018-04-07
    • 2016-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多