【问题标题】:MYSQL to UPDATE table if row with 2 specific columns exist or INSERT new row if it does not exist如果存在具有 2 个特定列的行,则 MYSQL 更新表;如果不存在,则插入新行
【发布时间】:2014-07-18 06:44:49
【问题描述】:

我有一个如下所示的 MYSQL 表:

id    id_jugador    id_partido    team1     team2
1        2              1           5         2
2        2              2           1         1
3        1              2           0         0

我需要创建一个查询以在表中插入新行或更新表。条件基于 id_jugadorid_partido,这意味着如果我想插入 id_jugador = 2id_partido = 1,那么它应该只用新的 team1 更新现有行和我发送的 team2 值。并且不要重复该行。

但是,如果我有一个条目 id_jugador=2id_partido=3,由于这个组合还不存在,它应该添加新行。

我阅读了关于 REPLACE INTO 的信息,但它似乎无法检查 UNIQUE KEYS 的组合。

【问题讨论】:

    标签: mysql replace insert sql-update unique-key


    【解决方案1】:

    如果您在(id_jugador, id_partido) 的两列上定义了一个 UNIQUE KEY,那么您可以使用:

    INSERT ... ON DUPLICATE KEY ...
    

    例如

    INSERT INTO mytable (id_jugador, id_partido, team1, team2) 
    VALUES (?, ?, ?, ?)
    ON DUPLICATE KEY
    UPDATE team1 = VALUES(team1)
         , team2 = VALUES(team2)
    

    (显然,我假设 id 是一个 AUTO_INCREMENT PRIMARY KEY,或者有一个 BEFORE INSERT 触发器在未提供时为 id 生成一个值。)

    MySQL 将尝试插入(使用 auto_increment id 值)。如果 INSERT 成功,MySQL 就完成了,它只是一个常规的插入。但是如果 INSERT 抛出了 DUPLICATE KEY 异常,那么 MySQL 会执行一个更新动作,相当于:

    UPDATE mytable SET team1 = ?, team2 = ? WHERE id_jugador = ? AND id_partido = ?
    

    请注意,可以在一个表上定义多个 UNIQUE KEY 约束。对于 UPDATE 操作的谓词,MySQL 将使用在 DUPLICATE KEY 异常中标识的任何唯一(或主)键的列/值。

    还要注意 MySQL 确实会尝试 INSERT,因此 MySQL 确实会用完 AUTO_INCREMENT 值,即使 INSERT 抛出 DUPLICATE KEY 异常也是如此。


    我通常避免使用REPLACE,因为我通常有很多外键,并且我不想要DELETE 操作。 REPLACE 执行的 DELETE 操作是“真正的”DELETE;如果存在外键引用,则将遵守与外键关联的 DELETE 规则...如果 DELETE 规则为 RESTRICT 或 NO ACTION 并且存在引用行,或者如果 DELETE 规则为 CASCADE 或 SET NULL,则删除将失败,引用行将被删除或更新。我也相信任何 BEFORE/AFTER DELETE 触发器也会被触发。


    除了这些选项之外,您还必须运行两个单独的语句。

    当我需要在没有定义唯一键的情况下避免插入时,我通常会执行以下操作:

    INSERT INTO mytable (id_jugador, id_partido, team1, team2) 
    SELECT i.*
      FROM (SELECT ? AS id_jugador, ? AS id_partido, ? AS team1, ? AS team2) i
      LEFT
      JOIN mytable s
        ON s.id_jugador <=> i.id_jugador
       AND s.id_partido <=> i.id_partido
     WHERE s.id IS NOT NULL
    

    语句执行后,测试受影响的行数。如果它为零,我们知道该行没有插入,所以我们可以继续进行更新。

    【讨论】:

    • 这很棒。但我有一个问题,如果我想组合考虑唯一键,我的意思是:id_jugador & id_partido 一起,它会工作吗?我想要的是仅当两个键匹配时才更新,如果只有 1 个键匹配,则 INSERT
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    相关资源
    最近更新 更多