In SQL, durante le modifiche di massa, è spesso necessario implementare uno scenario 'tutto o niente' - o tutte le modifiche vengono eseguite, o vengono annullate in caso di errore. Questo approccio viene raggiunto utilizzando le transazioni. La stored procedure deve avviare esplicitamente una transazione (BEGIN TRANSACTION), racchiudere le operazioni pertinenti, gestire gli errori e, in caso di errore, eseguire ROLLBACK, altrimenti - COMMIT.
Non bisogna dimenticare di gestire correttamente gli errori tramite costrutti come TRY...CATCH (SQL Server) o EXCEPTION (PostgreSQL).
Esempio per SQL Server:
CREATE PROCEDURE MassUpdate AS BEGIN BEGIN TRY BEGIN TRANSACTION; UPDATE Orders SET Status = 'Processed' WHERE Status = 'Pending'; UPDATE Inventory SET Stock = Stock - 1 WHERE ProductID IN (SELECT ProductID FROM Orders WHERE Status = 'Processed'); COMMIT TRANSACTION; END TRY BEGIN CATCH ROLLBACK TRANSACTION; -- Logging dell'errore THROW; END CATCH END
Domanda: È sufficiente utilizzare solo BEGIN TRANSACTION e COMMIT per garantire un rollback corretto delle modifiche in caso di errori in tutti i DBMS supportati?
Risposta: No, la transazione di per sé non cattura le eccezioni. È necessario utilizzare gestori (TRY...CATCH o analoghi) per catturare l'errore e chiamare esplicitamente ROLLBACK. In alcuni DBMS (ad esempio, MySQL con autocommit) potrebbe essere necessaria anche una configurazione aggiuntiva.
Esempio di codice errato (SQL Server):
BEGIN TRANSACTION; UPDATE Users SET Name = 'Ivan' WHERE ID = 1; UPDATE Orders SET Amount = Amount/0 WHERE UserID = 1; -- Errore di divisione per 0 COMMIT TRANSACTION;
In questo caso, se si verifica un errore, la transazione rimarrà aperta e le modifiche nella prima tabella potrebbero essere salvate.
Storia
Nella progettazione di un negozio online, è stata dimenticata la gestione degli errori nelle transazioni, il che ha portato a una perdita parziale di dati correlati: se si verificava un problema nell'aggiornamento dello stock durante l'aggiornamento dell'ordine, solo alcune modifiche venivano annullate, compromettendo l'integrità delle informazioni.
Storia
In un progetto di BI analytics è stato implementato un ricalcolo di massa dei report tramite procedura senza un controllo esplicito delle transazioni e senza gestione degli errori. Risultato: alcuni report sono stati aggiornati, altri no. I dati finali sono risultati non coerenti, poiché le situazioni di emergenza non portavano a un rollback atomico.
Storia
In un'azienda ci si fidava erroneamente dell'autocommit in MySQL, non impostando la modalità delle transazioni per operazioni di grandi dimensioni. In caso di guasto del server, parte dei dati era già stata registrata, altra no, il che ha causato lunghe operazioni di recupero e la perdita di parte degli ordini.