Voici encore une autre approche, qui selon moi est adaptée au cas particulier où une procédure doit être appelée directement par un utilisateur plutôt que par une application. Je dois dire, il propose moins de problèmes pour l'utilisateur alors que plus (peut-être, de façon disproportionnée) pour le développeur par rapport à la plupart des autres suggestions. Vous décidez si cela vous convient.
De toute façon, c'est parti.
D'abord, vous créez une table spéciale, CriticalCalls
, pour enregistrer les appels aux procédures critiques. Le tableau aurait une structure comme celle-ci:
SPID int,
ProcName sysname,
CallTime datetime
Fondamentalement, l'idée est qu'une SP critique doit être appelé deux fois: d'abord, il enregistre son appel et informe l'utilisateur de répéter l'appel dans un certain intervalle de temps une confirmation de leur intention, et avec le second appel, s'il est fait en conséquence, il procède réellement à l'achèvement de sa tâche.
Ainsi, la partie de départ de toute procédure critique aurait cette logique:
IF NOT EXISTS (
SELECT *
FROM CriticalCalls
WHERE SPID = @@SPID AND ProcName = @ThisProcName
AND GETDATE() - CallTime BETWEEN @LowerCallTimeLimit AND @UpperCallTimeLimit
/* the actual test for the time interval might be somewhat different */
) BEGIN
... /* upsert CriticalCalls with the current time stamp */
PRINT 'To proceed, please call this procedure again within...';
RETURN;
END;
DELETE FROM CriticalCalls WHERE SPID = @@SPID AND ProcName = @ThisProcName;
... /* proceed with your critical task */
En fait, je pense, il serait préférable d'utiliser un SP dédié (du nom CheckCriticalCalls
ci-dessous) pour toutes les manipulations avec CriticalCalls
, y compris toutes les modifications nécessaires. CheckCriticalCalls
recevrait le nom de la procédure à vérifier et renverrait une sorte d'indicateur indiquant si la procédure spécifiée devrait effectuer son opération réelle.
Il peut sembler un peu comme ceci:
EXECUTE @result = CheckCriticalCalls 'ThisProcedureName';
IF @result = -1 BEGIN
PRINT 'Call me again';
RETURN;
END;
... /* go on with the task */
L'idée derrière le réglage de la limite inférieure de l'intervalle est simplement d'empêcher l'utilisateur d'appeler une procédure critique deux fois automatiquement, soit en exécutant deux lignes EXECUTE...
identiques en un lot. La limite supérieure, bien sûr, est nécessaire pour 1) s'assurer que l'utilisateur confirme son intention très récente d'effectuer l'opération critique; 2) empêcher l'exécution si l'enregistrement existant dans CriticalCalls
est réellement laissé là d'une session passée avec le même SPID. Donc, en gros, un intervalle de 1-2 secondes à une demi-minute me semble tout à fait naturel. Vous pourriez choisir des chiffres différents à la place. Pourquoi ne configurez-vous pas d'autorisations pour vos process stockés?
De cette façon, seuls les utilisateurs autorisés peuvent l'exécuter. –
@The Elite Gentleman: Je ne dis pas que les utilisateurs autorisés peuvent parfois vouloir se sentir comme des êtres humains plutôt que des machines. Ce cas particulier montre plutôt que certains développeurs ne voient pas d'inconvénient à percevoir les utilisateurs comme de simples mortels. :) –