在 MySQL 中的一个查询中更新具有不同值的多行

问题描述 投票:0回答:9

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

例如,1 个查询中有 3 个更新:

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'; 

阅读一个例子,但我真的不明白如何进行查询。即:

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
9个回答
309
投票

你可以这样做:

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';

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


187
投票

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 列表中。 如果它们都不是主键(这似乎不太可能),那么这种方法将始终创建新记录 - 可能不是我们想要的。

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


21
投票
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';

16
投票

您可以使用

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';

7
投票

扩展@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 步:删除临时表


2
投票

在 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 个原始数据中的事务、插入、案例方法进行比较。

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

可以看到,多语句查询比最高答案效率更高。

以防万一您收到如下错误消息:

PHP Warning:  Error while sending SET_OPTION packet

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

max_allowed_packet


1
投票
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 每行的不同值


0
投票

如果您的表在 user_rol 和 cod_office 两列上有唯一键,则 INSERT INTO ... ON DUPLICATE KEY UPDATE ... 可以是如下解决方案,但它使用间隙锁(https://dev.mysql.com/ doc/refman/8.3/en/innodb-locking.html#innodb-gap-locks)所以如果并行执行多个语句,很有可能出现死锁。

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)

在 MySQL 5.x 中,您可以像这样使用 CASE WHEN THEN

UPDATE table_users 
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';

在 MySQL 8.x 中,您可以使用 VALUES 连接表 (https://dev.mysql.com/doc/refman/8.0/en/values.html)。我更喜欢这个解决方案,因为语法很明显、更短,当然也更容易维护。

UPDATE table_users
SET date = '12082014', cod_user = temp_data.column_1
FROM (VALUES
  ROW('student', '622057'),
  ROW('assistant', '2913659'),
  ROW('admin', '6160230'),
) as temp_data
WHERE user_rol = temp_data.column_0 AND cod_office = '17389551';

-9
投票

我是这样做的:

<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;
}

效果很好

© www.soinside.com 2019 - 2024. All rights reserved.