UPDATE modifica le righe esistenti
INSERT aggiunge nuove righe. UPDATE modifica righe che esistono già. La forma è breve e vale la pena impararla a memoria:
UPDATE table_name
SET column = value
WHERE condition;
Un esempio funzionante:
SET dice cosa cambia. WHERE dice quali righe. Il resto della tabella non viene toccato.
In pratica la clausola WHERE non è facoltativa
Tecnicamente WHERE è facoltativa. In pratica, ometterla è il modo in cui chi è alle prime armi si rovina il pomeriggio:
UPDATE users SET status = 'inactive';
-- ora tutti gli utenti sono inattivi
Senza filtro, ogni riga corrisponde. SQLite obbedisce in silenzio. Scrivi sempre prima la WHERE e poi la SET: questa sola abitudine evita un sacco di incidenti.
Se non sei sicuro che la tua WHERE sia giusta, esegui prima la stessa condizione con una SELECT:
Stessa condizione, due istruzioni. La SELECT è la tua prova a secco.
Aggiornare più colonne
Separa con delle virgole le assegnazioni dentro una sola SET. Una SET, tante colonne:
Un solo viaggio al database, una riga modificata, tre colonne aggiornate. Non scrivere tre istruzioni UPDATE separate quando ne basta una.
Espressioni a destra di =
Il valore dopo = non deve per forza essere un letterale. Può essere qualsiasi espressione, anche una che fa riferimento al valore attuale della colonna:
price * 1.10 legge il prezzo esistente, lo moltiplica e riscrive il risultato. SQLite valuta il lato destro usando i valori attuali della riga prima che qualsiasi assegnazione di questa istruzione abbia effetto, quindi puoi fare riferimento a più colonne in sicurezza:
UPDATE products SET price = price * 1.10, stock = stock + price;
-- qui 'price' sul lato destro è il prezzo VECCHIO, non quello appena aggiornato.
UPDATE ... FROM: prendere valori da un'altra tabella
Da SQLite 3.33, UPDATE supporta una clausola FROM per gli aggiornamenti tra tabelle. È il modo più pulito per sincronizzare dati tra tabelle:
La subquery calcola i totali per cliente; l'UPDATE esterno unisce quei risultati a customers tramite id. Senza UPDATE ... FROM dovresti scrivere una subquery correlata per ogni colonna, molto più rumorosa.
Alcune regole da tenere a mente:
- La tabella di destinazione va dopo
UPDATE, non nell'elenco delFROM. - È la clausola
WHEREa fare il join: qui non c'è la parola chiaveON. - Se il join può trovare più di una riga nel
FROM, il risultato non è definito. Assicurati che le chiavi del join producano al massimo una corrispondenza per ogni riga di destinazione.
RETURNING: vedere cosa è cambiato
SQLite (3.35+) permette a UPDATE di restituire le righe modificate nella stessa istruzione. Comodo quando la tua applicazione ha bisogno dei valori dopo l'aggiornamento senza una SELECT successiva:
Ricevi le righe effettivamente toccate, con i loro nuovi valori. Risparmi un viaggio al database ed elimini un'intera categoria di race condition nel codice concorrente. Più avanti in questo capitolo c'è una pagina intera su RETURNING.
UPDATE OR REPLACE: gestire i conflitti con i vincoli
Se il tuo aggiornamento violerebbe un vincolo UNIQUE, il comportamento predefinito è interrompere l'istruzione con un errore. La clausola OR ti permette di scegliere una politica diversa:
Le opzioni sono OR ABORT (predefinita), OR REPLACE, OR IGNORE, OR FAIL e OR ROLLBACK. REPLACE è quella pericolosa: elimina la riga in conflitto, e questo può propagarsi attraverso le chiavi esterne. Usala solo quando intendi davvero "se esiste già una riga con questo valore univoco, buttala via".
Per la maggior parte del lavoro in stile upsert, la sintassi dedicata INSERT ... ON CONFLICT è più chiara. C'è una pagina apposita.
Racchiudi gli aggiornamenti rischiosi in una transazione
Quando modifichi molte righe o esegui più istruzioni UPDATE che devono riuscire insieme, racchiudile in una transazione. Se qualcosa va storto, puoi fare rollback allo stato precedente:
Se la seconda istruzione fallisce (per esempio per un vincolo), ROLLBACK annulla la prima. Senza una transazione resteresti con un trasferimento a metà: Ada con 25 in meno, Boris invariato. Le transazioni hanno un capitolo tutto loro più avanti; per ora ti basta sapere che esistono e che gli aggiornamenti massivi vanno quasi sempre dentro una transazione.
Errori comuni
Un breve elenco di cose che fanno male:
- Dimenticare
WHERE: aggiorna ogni riga. Leggi la tua istruzione ad alta voce prima di eseguirla. - Operatore sbagliato nella
WHERE:WHERE status = NULLnon corrisponde a niente. UsaIS NULL. Lo vediamo nella pagina sugli operatori. - Aggiornare con una subquery che restituisce più di una riga quando te ne aspetti una. Usa
LIMIT 1o aggrega la subquery, altrimenti otterrai errori o risultati sorprendenti. - Confondere UPDATE OR REPLACE con UPSERT.
OR REPLACEelimina le righe in conflitto.INSERT ... ON CONFLICT DO UPDATEle modifica sul posto. Sono operazioni diverse.
Prossimo passo: DELETE
UPDATE modifica le righe; DELETE le rimuove. Vale la stessa disciplina con la WHERE, e la stessa abitudine di "eseguire prima una SELECT" ti salverà dagli stessi tipi di disastro. È la prossima pagina.
Domande frequenti
Qual è la sintassi di base di UPDATE in SQLite?
UPDATE table_name SET column = value WHERE condition;. La clausola SET elenca le colonne che vuoi cambiare e i loro nuovi valori. La clausola WHERE sceglie quali righe modificare: se la ometti, viene aggiornata ogni riga della tabella.
Come aggiorno più colonne con una sola istruzione?
Separa le assegnazioni con delle virgole dentro la clausola SET: UPDATE users SET name = 'Ada', email = 'ada@x.com' WHERE id = 1;. Un'istruzione, un solo viaggio al database, una riga aggiornata. Non ripetere SET per ogni colonna.
SQLite può aggiornare una tabella a partire da un'altra tabella?
Sì: UPDATE ... FROM (aggiunto in SQLite 3.33) ti permette di unire un'altra tabella o una subquery all'aggiornamento. Scrivi UPDATE target SET col = source.col FROM source WHERE target.id = source.id;. È il modo più pulito per copiare valori tra tabelle.