Petit rappel sur les transactions

Dans une application, lorsque l’on veut s’assurer qu’un ensemble d’opération va s’exécuter entièrement ou pas du tout, on peut utiliser des transactions.

Sans rentrer dans les détails vous pouvez commencer par aller voir la classe TransactionScope du Framework .Net et au niveau de SQL Server les instructions de transactions.

Or parfois il est utile, voire indispensable, d’écrire des scripts SQL pour modifier des données en base, ne serait-ce que pour des opérations de type batch (supprimer des données de tests, corriger des données issues d’un bogue applicatif, etc. ) qui n’ont pas à être rejoués plus tard et qui ne nécessitent pas par conséquent un développement spécifique dans un back-office ou ailleurs.

Application à des scripts manuels

Lorsque l’on fait ce genre d’opération il est préférable (surtout lorsqu’il s’agit d’une base de production) de vérifier ce que l’on fait.

Pour cela, il est possible d’utiliser les transactions de cette manière :

BEGIN TRANSACTION 
 
-- Requête à tester

ROLLBACK
 
-- COMMIT

Les éléments se trouvant entre le BEGIN TRANSACTION et le ROLLBACK seront exécutés puis annulés. Il est ainsi possible de voir dans les messages réponse si le nombre de lignes affectés par notre requête nous semble cohérent ou si des messages d’erreurs apparaissent.

messages

Pour avoir un meilleur aperçu, il est aussi possible de faire un SELECT avant le ROLLBACK :

BEGIN TRANSACTION 
 
-- Requête à tester
DELETE FROM [dbo].[Customer] WHERE [Customer_Email] <> '[email protected]'
 
-- Vérification de la requête
SELECT * FROM [dbo].[Customer] 
 
-- La requête n'était pas bonne => On annule tout 
--ROLLBACK 
 
-- Autrement => On valide les modifications 
--COMMIT

results

Si l’on est sûr de sa requête il suffit de d’exécuter le COMMIT, sinon il faut exécuter le ROLLBACK.

Automatisons le processus

Avec les exemples ci-dessus, on voit qu’une action manuelle reste nécessaire, mais parfois on écrit un script et on le passe à un DBA ou à un technicien système qui va ensuite jouer ce script. Il n’a pas forcément la connaissance fonctionnelle permettant de valider ou non le résultat de la requête (et en outre il a probablement autre chose à faire).

Dans ce cas, nous pouvons lui mâcher le travail en automatisant un peu plus le script.

Par exemple supposons que nous devons écrire un script permettant de supprimer un utilisateur test mais que nous souhaitons tout de même vérifier que nous n’en supprimons qu’un seul (ou aucun).

BEGIN TRANSACTION

DELETE FROM [dbo].[Customer] WHERE [Customer_Name] = 'Doe'

 -- Vérification de la requête
IF @@ROWCOUNT > 1
BEGIN
    ROLLBACK
    PRINT 'Suppression annulée, trop d''enregistrements'
END
ELSE
    COMMIT
    PRINT 'Suppression effectuée'

Si on veut vraiment attirer l’attention de la personne qui va jouer le script, on peut remplacer le premier PRINT par un RAISEERRORavec une sévérité au moins égale à 11 (mais pas trop non plus, inutile de crier au feu) pour que le moteur SQL utilise le style des erreurs.

BEGIN TRANSACTION

DELETE FROM [dbo].[Customer] WHERE [Customer_Name] = 'Doe'

-- Vérification de la requête
IF @@ROWCOUNT > 1
BEGIN
    ROLLBACK
    RAISERROR (N'Suppression annulée, trop d''enregistrements', 11, 1);
END
ELSE
    COMMIT
    PRINT 'Suppression effectuée'

Pour obtenir ceci :

messages

En effet, il serait probablement contre-productif de vouloir traiter tous les cas d’erreurs possibles. Il est parfois aussi simple d’anticiper un échange avec la personne qui a un accès à la base de production et d’ajuster le script en fonction des éventuelles erreurs.

Conclusion

Voilà, ce n’est pas grand chose, mais avec un peu de chance, cet article vous évitera de faire des erreurs bêtes sur les données de production.

Ne ratez plus aucunes actualités avec la newsletter mensuelle de SoftFluent