Lavorare con un database è un po' come la vita di un programmatore: piena di sorprese. Anche il dev più esperto può sbagliare, tipo cancellare dati per sbaglio, provare a inserire un duplicato o rompere i vincoli di integrità. Ma non basta solo evitare questi errori: è importante anche sapere come sistemarli se succedono. Vediamo insieme alcuni degli errori più tipici.
Errore n°1: Mancanza della condizione WHERE
L'errore più classico che fanno i principianti (e, dai, a volte anche i dev esperti) è dimenticarsi di aggiungere WHERE in una query di update o delete. Le query senza WHERE aggiornano o cancellano tutte le righe della tabella.
-- Esempio di cosa NON fare:
UPDATE students SET status = 'laureato';
-- Oppure così:
DELETE FROM students;
Conseguenze: immagina che dopo questa query ti accorgi che la tua tabella students, con tutti i dati degli studenti, è vuota. E la cosa peggiore: non puoi recuperare i dati se non hai un backup o non hai usato le transazioni (e anche in quel caso... stress assicurato).
Come evitarlo: aggiungi sempre condizioni nelle query UPDATE e DELETE per specificare esattamente quali righe vuoi cambiare o cancellare.
-- Così va fatto:
UPDATE students
SET status = 'laureato'
WHERE year_of_study = 4;
DELETE FROM students
WHERE status = 'espulso';
Un altro trucco: prima di fare una delete, lancia sempre una SELECT per controllare che la condizione sia giusta:
-- Prima controlla:
SELECT * FROM students WHERE status = 'espulso';
-- Poi cancella:
DELETE FROM students WHERE status = 'espulso';
Errore n°2: Violazione dell'unicità dei dati (UNIQUE)
Se sulla tabella c'è un vincolo UNIQUE, provare a inserire un duplicato ti darà errore.
-- Errore per duplicazione email:
INSERT INTO students (name, email) VALUES ('Otto Lin', 'otto.lin@email.com');
INSERT INTO students (name, email) VALUES ('Peter Pen', 'otto.lin@email.com');
Errore:
ERROR: duplicate key value violates unique constraint "students_email_key"
Come evitarlo: prima di inserire dati, controlla che non ci sia già una riga con gli stessi valori.
-- Un modo:
SELECT * FROM students WHERE email = 'otto.lin@email.com';
-- Oppure usa UPSERT:
INSERT INTO students (name, email)
VALUES ('Peter Pen', 'otto.lin@email.com')
ON CONFLICT (email) DO NOTHING;
Errore n°3: Violazione dei vincoli di integrità (FOREIGN KEY)
Supponiamo che hai due tabelle: students e enrollments, dove student_id in enrollments è una foreign key che punta a id in students. Se provi a inserire una riga in enrollments con uno student_id che non esiste in students, avrai errore.
INSERT INTO enrollments (student_id, course_id)
VALUES (999, 101); -- Errore, perché student_id 999 non esiste
Come evitarlo?
- Controlla sempre che la riga esista nella tabella "genitore" prima di inserire nella tabella collegata:
SELECT * FROM students WHERE id = 999;
- Usa il vincolo
ON DELETE CASCADEper cancellare automaticamente le righe collegate quando cancelli dalla tabella genitore (ma usalo con attenzione).
CREATE TABLE enrollments (
id SERIAL PRIMARY KEY,
student_id INT REFERENCES students(id) ON DELETE CASCADE,
course_id INT
);
Errore n°4: Tipi di dati sbagliati
Quando inserisci o aggiorni dati, PostgreSQL controlla rigorosamente la compatibilità dei tipi. Se provi a inserire una stringa in un campo numerico, avrai errore.
-- Errore per incompatibilità di tipo:
INSERT INTO students (id, name) VALUES ('abc', 'Alex Go');
Errore:
ERROR: invalid input syntax for type integer
Come evitarlo? Fai attenzione ai tipi di dati nei valori che inserisci. Se i dati arrivano da una form utente, validali sempre lato applicazione.
Errore n°5: Problemi di accesso parallelo (perdita di dati)
Immagina che due utenti provino a modificare la stessa riga nello stesso momento. Senza una corretta isolamento delle transazioni, rischi conflitti.
-- Utente A:
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
-- Utente B:
BEGIN;
UPDATE accounts SET balance = balance - 50 WHERE id = 1;
Come evitarlo? Usa le transazioni e i livelli di isolamento per evitare modifiche simultanee ai dati.
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;
Errore n°6: Perdita di dati per colpa di TRUNCATE
TRUNCATE cancella tutte le righe della tabella senza possibilità di recupero, perché questo comando non supporta ROLLBACK (non attiva i trigger e viene eseguito subito).
-- Cancella tutto senza ritorno:
TRUNCATE TABLE students;
Come evitarlo: usa DELETE con una condizione invece di TRUNCATE se vuoi poter fare rollback.
BEGIN;
DELETE FROM students WHERE year_of_study = 1;
-- Se cambi idea:
ROLLBACK;
Errore n°7: Mancanza di transazioni per operazioni importanti
Se fai un'operazione complessa in più step e a metà succede un errore, i dati possono restare in uno stato inconsistente.
-- Step 1: aggiungi uno studente
INSERT INTO students (name, email) VALUES ('Otto Lin', 'otto.lin@email.com');
-- Step 2: lo iscrivi a un corso
INSERT INTO enrollments (student_id, course_id) VALUES (LASTVAL(), 101); -- errore
Come evitarlo? Metti queste operazioni in una transazione:
BEGIN;
INSERT INTO students (name, email) VALUES ('Ivan Ivanov', 'ivan.ivanov@email.com');
INSERT INTO enrollments (student_id, course_id) VALUES (LASTVAL(), 101);
COMMIT;
Se in qualsiasi step c'è un errore, puoi annullare tutto:
ROLLBACK;
Errore n°8: Lavorare per sbaglio con NULL
NULL spesso porta sorprese, perché non è né zero né stringa vuota, e i confronti con lui possono dare risultati strani.
-- Questo non funziona:
SELECT * FROM students WHERE email = NULL;
Come evitarlo? Usa IS NULL o IS NOT NULL:
SELECT * FROM students WHERE email IS NULL;
Gli errori tipici sono inevitabili, ma se sai riconoscerli e come evitarli, puoi lavorare con i dati in modo sicuro ed efficace. PostgreSQL è severo ma giusto: ti segnala sempre l'errore se qualcosa non va. Ricorda solo che gli errori non sono nemici, ma maestri.
GO TO FULL VERSION