MySQL - ACTUALIZA múltiples filas con diferentes valores en una consulta

139

Estoy tratando de entender cómo ACTUALIZAR varias filas con diferentes valores y simplemente no lo entiendo. La solución está en todas partes, pero para mí parece difícil de entender.

Por ejemplo, tres actualizaciones en 1 consulta:

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

Yo leí un ejemplo, pero realmente no entiendo cómo hacer la consulta. es decir:

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

No tengo del todo claro cómo hacer la consulta si hay varias condiciones en el DÓNDE y en la condición SI ... ¿alguna idea?

franvergara66
fuente
¿Responde esto a tu pregunta? Múltiples actualizaciones en MySQL
PeterPan666

Respuestas:

188

Puedes hacerlo de esta manera:

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

No entiendo tu formato de fecha. Las fechas deben almacenarse en la base de datos utilizando tipos de fecha y hora nativos.

Gordon Linoff
fuente
cómo puedo hacer para que se ejecute la actualización, si el registro ya existe
franvergara66
1
@ franvergara66. . . No entiendo tu comentario. updates solo afecta a los registros que ya existen.
Gordon Linoff
Disculpe, señor inglés, cuando trato de hacer una actualización, mysql me da el error: # 1062 - Duplicar la entrada 'XXX' para la clave 'PRIMARIO'. Eso ocurre cuando trato de actualizar un registro con el mismo valor que ya tenía, ¿hay alguna forma de omitir la actualización si el valor actual es el mismo que el actualizado?
franvergara66
1
@ franvergara66. . . Puede que tengas un problema diferente. Si cod_useres una clave principal y los valores se están barajando, entonces la mejor ruta es probablemente varias actualizaciones.
Gordon Linoff
1
sí, ya veo, el verdadero problema es que hay varios asistentes, y cuando se intenta hacer una actualización, se viola la integridad de la clave principal. Muchas gracias por tu tiempo.
franvergara66
109

MySQL permite una forma más legible de combinar múltiples actualizaciones en una sola consulta. Esto parece ajustarse mejor al escenario que describe, es mucho más fácil de leer y evita esas múltiples condiciones difíciles de desenredar.

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)

Esto supone que la user_rol, cod_officecombinación es una clave principal. Si solo uno de estos es la clave principal , agregue el otro campo a la lista ACTUALIZAR. Si ninguno de ellos es una clave principal (que parece poco probable), este enfoque siempre creará nuevos registros, probablemente no lo que se desea.

Sin embargo, este enfoque hace que las declaraciones preparadas sean más fáciles de construir y más concisas.

Trevedhek
fuente
44
¡Gracias! Esto es lo que estaba buscando durante mucho tiempo, la forma más limpia, no pude entender esta sintaxis, específicamente cod_user=VALUES(cod_user), ..., incluso de documentos oficiales de MySQL 5.6
Yuriy Dyachkov
18
Nota: Esto agregará nuevas filas si la clave no existe en la tabla, lo que resulta en registros no deseados.
Faraz
1
Difícil de usar un IODKU que nunca se inserta, pero muy elegante.
Tom Desp
Y tenga en cuenta que este enfoque requiere clave primaria se establece para la tabla.
FlameStorm
55
Esto no funciona si omite las columnas que no pueden ser nulas, ya que sql todavía intenta crear un nuevo registro antes de recurrir a la actualización.
Arno van Oordt
15

Puede usar una CASEdeclaración para manejar múltiples escenarios 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';
Hart CO
fuente
1
Hizo un error tipográfico al final de la declaración CASE: tiene 2 comas una al lado de la otra.
pmrotule
8
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';
Akshay Bhan
fuente
0

Para ampliar la respuesta de @Trevedhek ,

En caso de que la actualización se haga con claves no únicas, se necesitarán 4 consultas

NOTA: Esto no es seguro para transacciones

Esto se puede hacer usando una tabla temporal.

Paso 1: cree una clave de tabla temporal y las columnas que desea actualizar

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

Paso 2: inserte los valores en la tabla temporal

Paso 3: actualice la tabla original

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

Paso 4: suelte la tabla temporal

Sab
fuente
0
UPDATE Table1 SET col1= col2 FROM (SELECT col2, col3 FROM Table2) as newTbl WHERE col4= col3

Aquí col4 y col1 están en la Tabla1. col2 y col3 están en la Tabla2
Estoy tratando de actualizar cada col1 donde col4 = col3 valor diferente para cada fila

ankit giri
fuente
-1

Lo hice de esta manera:

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

donde está PushSettings

public class PushSettings {

    private List<PushSetting> settings;
    private String userId;
}

funciona bien

ru51an
fuente
el autor quiere 1 consulta, está claro que puede hacerlo con foreach, lo que hará varias consultas
Hristo93