Question

J'ai une procédure stockée qui est en train de faire beaucoup de suppression. Des centaines de milliers de dossiers. Il ne va pas être runnable de l'application, mais encore, je suis préoccupé, que l'un de mes clients exécute accidentellement (j'ai eu des problèmes antérieurs en raison de leur « curiosité »): D

Oui. il y a des sauvegardes et des trucs comme ça, mais je pensais .... ne pas les effrayer ... est-il possible de demander à l'utilisateur « êtes-vous sûr? » avant de l'exécuter? :) merci

Était-ce utile?

La solution

Je suppose que vous pourriez avoir un paramètre appelé « confirmation » qui nécessite une chaîne spécifique (e, g, « Je sais ce que je fais ») pour être transmis, si elle est pas définie, ou est mal réglé, juste retour de la procédure sans exécuter le code principal. Pas exactement ce que vous vouliez, mais il est une option.

par exemple, - (syntaxe non testé et probablement terribles)

CREATE PROCEDURE dbo.mySproc (
@Confirmation Varchar(100)
) AS
BEGIN
    if(@Confirmation <> 'I know what I am doing')
    BEGIN
        return;
    END
    DELETE from table_name where condition
END

Autres conseils

En bref, non.

La théorie est que tout le monde avec des autorisations pour trouver et être en mesure d'exécuter une procédure stockée, devrait être autorisé. Il serait préférable de limiter les autorisations pour que ceux qui ont une curiosité excessive n'ont pas les autorisations pour exécuter cela.

L'autre, option moins sûre serait d'exiger un secret prédéfini qui doit être passé en paramètre - bien sûr, ils pourraient tout scénario de la procédure stockée loin pour trouver le secret si ...

Bien sûr, l'autre point serait la suivante: Si ce n'est pas appelable, pourquoi l'inclure? Après tout, quand vous venez de faire des tâches de type admin, vous pouvez avoir les déclarations de script dans un fichier que vous pouvez garder en sécurité sur votre propre machine

utiliser une approche à plusieurs niveaux volets:

1) contrôle l'exécution de la sécurité, comme:

GRANT EXECUTE ON [dbo].[yourProcedure] TO [userxyz]

2) utiliser un nom de procédure vraiment descriptive / effrayant, comme

CREATE PROCEDURE Will_Delete_All_Your_Data ...

3) mettre un grand accrocheur commentaire au début de la procédure stockée

--NOTE, will delete all of your data--
--NOTE, will delete all of your data--
--NOTE, will delete all of your data--
--NOTE, will delete all of your data--
--NOTE, will delete all of your data--

4) faire passer de l'utilisateur dans un code d'accès spécial obscurcie:

CREATE PROCEDURE Will_Delete_All_Your_Data
(
    @SpecialCode varchar(30)
)

IF @SpecialCode!=CHAR(83)+CHAR(112)+CHAR(101)+CHAR(99)+CHAR(105)+CHAR(97)+CHAR(108)+CHAR(67)+CHAR(111)+CHAR(100)+CHAR(101)
BEGIN
    RETURN 999
END
...

Pour votre information, le code spécial doit être 'SpecialCode' ou RETOUR 999 est touché.

Vous pouvez ajouter un paramètre @reallyReallyReallyDelete à la sproc qui servira de mesure de sécurité. Si elle est réglée sur YesYesYes engagera effectivement la transaction

Vous pouvez utiliser une entrée peu appelé @UserKnowsWhatTheyAreDoing et vérifier s'il est vrai avant d'exécuter. Si c'est faux, imprimer un message amical et revenir grâce à la procédure

La procédure peut exiger un argument d'une valeur spécifique, comme 'Yes I know what I'm doing'. Ou il peut rechercher une ligne d'une table spéciale avec une confirmation similaire et un horodatage récent.

Voici encore une autre approche, qui je pense est bon pour le cas particulier lorsqu'une procédure doit être appelé par un utilisateur directement plutôt que d'une application.

Je dois dire, il propose moins de problèmes pour l'utilisateur en plus (peut-être, de manière disproportionnée) pour le développeur par rapport à la plupart des autres suggestions. Vous décidez si cela vous convient.

Quoi qu'il en soit, va ici.

D'abord, vous créez une table spéciale, CriticalCalls, pour enregistrer les appels aux procédures critiques. Le tableau aurait une structure comme ceci:

SPID int,
ProcName sysname,
CallTime datetime

En fait, 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 comme une confirmation de leur intention, et avec le deuxième appel, si en conséquence, elle procède effectivement à remplir 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é (appelé 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 renvoyer une sorte de drapeau indiquant si la procédure spécifiée doit effectuer son fonctionnement réel.

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, à savoir par l'exécution de deux lignes de EXECUTE... identiques en un seul lot. La limite supérieure, bien sûr, est nécessaire pour 1) veiller à ce 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 en fait laissé là d'une dernière session avec le même SPID.

Donc, en gros, un intervalle de 1-2 secondes à une demi-minute semble tout à fait naturel pour moi. Vous pouvez choisir différents chiffres à la place.

Avez-vous besoin de les supprimer vraiment de la DB? Si je peux me permettre l'espace supplémentaire que je vais mettre un drapeau « supprimé » dans mes tableaux et une dernière colonne mise à jour. De cette façon, si un enregistrement est accidentellement supprimé au moins je peux habituellement le suivre vers le bas et restaurer assez facilement. Juste une pensée.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top