【问题标题】:MySQL - UPDATE multiple rows with different values in one queryMySQL - 在一个查询中更新具有不同值的多行
【发布时间】:2014-10-29 17:59:27
【问题描述】:

我试图了解如何使用不同的值更新多行,但我只是不明白。解决方案无处不在,但对我来说似乎很难理解。

例如,1 个查询中的三个更新:

UPDATE table_users
SET cod_user = '622057'
    , date = '12082014'
WHERE user_rol = 'student'
    AND cod_office = '17389551'; 

UPDATE table_users
SET cod_user = '2913659'
    , date = '12082014'
WHERE user_rol = 'assistant'
    AND cod_office = '17389551'; 

UPDATE table_users
SET cod_user = '6160230'
    , date = '12082014'
WHERE user_rol = 'admin'
    AND cod_office = '17389551'; 

我以read 为例,但我真的不明白如何进行查询。即:

UPDATE table_to_update
SET cod_user= IF(cod_office = '17389551','622057','2913659','6160230')
    ,date = IF(cod_office = '17389551','12082014')
WHERE ?? IN (??) ;

如果 WHERE 和 IF 条件中有多个条件,我不完全清楚如何进行查询..有什么想法吗?

【问题讨论】:

标签: mysql sql sql-update


【解决方案1】:

你可以这样做:

UPDATE table_users
    SET cod_user = (case when user_role = 'student' then '622057'
                         when user_role = 'assistant' then '2913659'
                         when user_role = 'admin' then '6160230'
                    end),
        date = '12082014'
    WHERE user_role in ('student', 'assistant', 'admin') AND
          cod_office = '17389551';

我不明白你的日期格式。日期应使用本地日期和时间类型存储在数据库中。

【讨论】:

  • 如果记录已经存在,我该怎么做才能执行更新
  • @franvergara66 。 . .我不明白你的评论。 updates 只影响已经存在的记录。
  • @franvergara66 。 . .你可能有不同的问题。如果cod_user 是主键并且值正在被洗牌,那么多次更新可能是最好的路线。
  • 是的,我明白了,真正的问题是有几个助手,然后在尝试进行更新时,主键的完整性被破坏了。非常感谢您的宝贵时间。
  • 请注意,这会将 user_role 设置为 NULL 对于返回的与三种情况之一不匹配的任何记录。考虑在结尾之前添加一个 ELSE,例如 ELSE cod_user,这样如果字段与 WHEN 子句不匹配,您可以将其设置为自身。
【解决方案2】:

您可以使用CASE 语句来处理多个 if/then 场景:

UPDATE table_to_update 
SET  cod_user= CASE WHEN user_rol = 'student' THEN '622057'
                   WHEN user_rol = 'assistant' THEN '2913659'
                   WHEN user_rol = 'admin' THEN '6160230'
               END
    ,date = '12082014'
WHERE user_rol IN ('student','assistant','admin')
  AND cod_office = '17389551';

【讨论】:

  • 您在 CASE 语句的末尾打错字了:两个逗号相邻。
【解决方案3】:

MySQL 允许以更易读的方式将多个更新组合到单个查询中。这似乎更适合您描述的场景,更容易阅读,并且避免了那些难以解开的多重条件。

INSERT INTO table_users (cod_user, date, user_rol, cod_office)
VALUES
('622057', '12082014', 'student', '17389551'),
('2913659', '12082014', 'assistant','17389551'),
('6160230', '12082014', 'admin', '17389551')
ON DUPLICATE KEY UPDATE
 cod_user=VALUES(cod_user), date=VALUES(date)

这假定user_rol, cod_office 组合是主键。如果其中只有一个是 主键,则将另一个字段添加到 UPDATE 列表中。 如果它们都不是主键(这似乎不太可能),那么这种方法总是会创建新记录——可能不是我们想要的。

但是,这种方法使准备好的语句更容易构建和更简洁。

【讨论】:

  • 谢谢!这是我一直在寻找的,最干净的方式,我无法弄清楚这个语法,特别是cod_user=VALUES(cod_user), ...,即使来自官方 MySQL 5.6 文档
  • 注意:如果键在表中不存在导致不需要的记录,这将添加新行。
  • 很难使用从不插入的 IODKU,但非常优雅。
  • 并注意这种方法require是为表设置主键的。
  • 如果省略任何不能为空的列,这将不起作用,因为 sql 在实际使用更新之前仍会尝试创建新记录。
【解决方案4】:
UPDATE table_name
SET cod_user = 
    CASE 
    WHEN user_rol = 'student' THEN '622057'
    WHEN user_rol = 'assistant' THEN '2913659'
    WHEN user_rol = 'admin' THEN '6160230'
    END, date = '12082014'

WHERE user_rol IN ('student','assistant','admin')
AND cod_office = '17389551';

【讨论】:

    【解决方案5】:

    扩展@Trevedhek answer

    如果必须使用非唯一键进行更新,则需要 4 次查询

    注意:这不是交易安全的

    这可以使用临时表来完成。

    第 1 步:创建临时表键和要更新的列

    CREATE TEMPORARY TABLE  temp_table_users
    (
        cod_user varchar(50)
        , date varchar(50)
        , user_rol varchar(50)
        ,  cod_office varchar(50)
    ) ENGINE=MEMORY
    

    第 2 步:将值插入临时表中

    第 3 步:更新原始表

    UPDATE table_users t1
    JOIN temp_table_users tt1 using(user_rol,cod_office)
    SET 
    t1.cod_office = tt1.cod_office
    t1.date = tt1.date
    

    第 4 步:删除临时表

    【讨论】:

      【解决方案6】:

      我是这样做的:

      <update id="updateSettings" parameterType="PushSettings">
          <foreach collection="settings" item="setting">
              UPDATE push_setting SET status = #{setting.status}
              WHERE type = #{setting.type} AND user_id = #{userId};
          </foreach>
      </update>
      

      PushSettings 在哪里

      public class PushSettings {
      
          private List<PushSetting> settings;
          private String userId;
      }
      

      效果很好

      【讨论】:

      • 作者想要 1 个查询,很明显他可以用 foreach 来完成,这将进行多个查询
      【解决方案7】:
      UPDATE Table1 SET col1= col2 FROM (SELECT col2, col3 FROM Table2) as newTbl WHERE col4= col3
      

      这里 col4 和 col1 在表 1 中。 col2 & col3 在 Table2
      我正在尝试更新每个 col1 其中 col4 = col3 每行的不同值

      【讨论】:

        【解决方案8】:

        在php中,你使用mysqli实例的multi_query方法。

        $sql = "SELECT COUNT(*) AS _num FROM test;
                INSERT INTO test(id) VALUES (1); 
                SELECT COUNT(*) AS _num FROM test; ";
        
        $mysqli->multi_query($sql);
        

        将结果与更新 30,000 raw 中的事务、插入、案例方法进行比较。

        交易:5.5194580554962
        插入:0.20669293403625
        案例:16.474853992462
        多:0.0412278175354

        如您所见,多语句查询比最高答案更有效。

        以防万一您收到这样的错误消息:

        PHP Warning:  Error while sending SET_OPTION packet
        

        你可能需要在mysql配置文件中增加max_allowed_packet

        【讨论】:

          猜你喜欢
          • 2023-03-23
          • 1970-01-01
          • 1970-01-01
          • 2019-01-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-08-22
          • 2020-10-14
          相关资源
          最近更新 更多