MySQL - AGGIORNA più righe con valori diversi in una query


139

Sto cercando di capire come AGGIORNARE più righe con valori diversi e non riesco a capirlo. La soluzione è ovunque ma per me sembra difficile da capire.

Ad esempio, tre aggiornamenti in 1 query:

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

Ho letto un esempio, ma davvero non capisco come fare la query. vale a dire:

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

Non sono del tutto chiaro come eseguire la query se ci sono più condizioni nella condizione WHERE e nella condizione IF ... qualsiasi idea?


Questo risponde alla tua domanda? Aggiornamenti multipli in MySQL
PeterPan666 il

Risposte:


188

Puoi farlo in questo modo:

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

Non capisco il tuo formato data. Le date devono essere archiviate nel database utilizzando tipi di data e ora nativi.


come posso fare in modo che l'aggiornamento venga eseguito, se il record esiste già
franvergara66

1
@ franvergara66. . . Non capisco il tuo commento. updates riguarda solo i record già esistenti.
Gordon Linoff,

Mi scusi, signore inglese, quando provo a fare un aggiornamento mysql mi dia l'errore: # 1062 - Voce duplicata "XXX" per la chiave "PRIMARY". Ciò accade quando provo ad aggiornare un record con lo stesso valore che aveva già, c'è un modo per saltare l'aggiornamento se il valore corrente è lo stesso dell'aggiornamento?
franvergara66,

1
@ franvergara66. . . Potresti avere un problema diverso. Se cod_userè una chiave primaria e i valori vengono mescolati, allora probabilmente più aggiornamenti sono la strada migliore.
Gordon Linoff,

1
sì, vedo, il vero problema è che ci sono diversi assistenti, quindi quando si tenta di fare un aggiornamento, l'integrità della chiave primaria viene violata. La ringrazio molto per il vostro tempo.
franvergara66

109

MySQL consente un modo più leggibile di combinare più aggiornamenti in una singola query. Questo sembra adattarsi meglio allo scenario che descrivi, è molto più facile da leggere ed evita quelle condizioni difficili da districare.

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)

Ciò presuppone che la user_rol, cod_officecombinazione sia una chiave primaria. Se solo una di queste è la chiave primaria , quindi aggiungere l'altro campo all'elenco AGGIORNAMENTO. Se nessuno dei due è una chiave primaria (che sembra improbabile), questo approccio creerà sempre nuovi record, probabilmente non ciò che si desidera.

Tuttavia, questo approccio rende le istruzioni preparate più facili da costruire e più concise.


4
Grazie! Questo è quello che stavo cercando da molto tempo, il modo più pulito, non riuscivo a capire questa sintassi, in particolare cod_user=VALUES(cod_user), ..., anche dai documenti ufficiali di MySQL 5.6
Yuriy Dyachkov,

18
Nota: questo aggiungerà nuove righe se la chiave non esiste nella tabella risultante in record indesiderati.
Faraz,

1
Difficile usare un IODKU mai inseribile, ma molto elegante.
Tom Desp,

E si noti che questo approccio richiede che la chiave primaria sia impostata per la tabella.
FlameStorm,

5
Questo non funziona se si omettono colonne che non possono essere nulle, poiché sql cerca ancora di creare un nuovo record prima di ricorrere effettivamente all'aggiornamento.
Arno van Oordt,

15

È possibile utilizzare CASEun'istruzione per gestire più scenari 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';

1
Hai fatto un refuso alla fine dell'istruzione CASE: hai 2 virgole l'una accanto all'altra.
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';

0

Per estendere la risposta di @Trevedhek ,

Nel caso in cui l'aggiornamento debba essere eseguito con chiavi non univoche, saranno necessarie 4 query

NOTA: questo non è sicuro per le transazioni

Questo può essere fatto usando una tabella temporanea.

Passaggio 1: creare le chiavi di una tabella temporanea e le colonne che si desidera aggiornare

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

Passaggio 2: inserire i valori nella tabella temporanea

Passaggio 3: aggiornare la tabella originale

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

Passaggio 4: rilasciare la tabella temporanea


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

Qui col4 e col1 sono nella tabella 1. col2 e col3 sono nella Tabella 2
Sto cercando di aggiornare ogni col1 dove col4 = col3 valore diverso per ogni riga


-1

L'ho fatto in questo modo:

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

dove PushSettings è

public class PushSettings {

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

funziona benissimo


autore vuole 1 query, è chiaro che può farlo con foreach, che farà diverse query
Hristo93
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.