Domanda

Ho una procedura immagazzinata che sta facendo un sacco di eliminazione. Centinaia di migliaia di dischi. Non sta per essere eseguibile dall'applicazione, ma ancora, mi riguarda, che uno dei miei clienti corre accidentalmente (ho avuto problemi precedenti a causa della loro "curiosità"): D

Sì. ci sono i backup e cose del genere, ma stavo pensando .... per non spaventarli ... c'è un modo per chiedere all'utente "Sei sicuro?" prima di eseguirlo? :) grazie

È stato utile?

Soluzione

Credo che si potrebbe avere un parametro chiamato "conferma" che richiede una stringa specifica (e, g, "Io so quello che sto facendo") per essere passato in, se non è impostata, o non è impostato correttamente, basta ritorno dalla procedura senza eseguire il codice principale. Non è esattamente quello che volevi, ma è un'opzione.

per esempio - (sintassi non testato e probabilmente terribile)

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

Altri suggerimenti

In breve, no.

La teoria va che chiunque con le autorizzazioni per trovare e essere in grado di eseguire una stored procedure, dovrebbe essere consentito. Sarebbe meglio per limitare le autorizzazioni in modo che quelli con una curiosità in eccesso non hanno le autorizzazioni per eseguire questo.

L'altra, meno sicura, opzione sarebbe quella di richiedere un segreto predefinito che deve essere passato come parametro - naturalmente potevano solo script di stored procedure a cercare il segreto anche se ...

Naturalmente, l'altro punto sarebbe: Se non è richiamabile, perché includerlo? Dopo tutto, quando si arriva a fare i compiti di tipo amministratore, è possibile avere il bilancio sceneggiato fuori come un file che è possibile mantenere sicuro sulla propria macchina

utilizzare un duplice approccio a più livelli:

1) Controllo esecuzione di sicurezza, come:

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

2) utilizzare un / spaventoso nome procedura molto descrittivo, come

CREATE PROCEDURE Will_Delete_All_Your_Data ...

3) ha messo un grande occhio cattura commento all'inizio della stored procedure

--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) far passare l'utente in un codice di accesso speciale offuscato:

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
...

Cordiali saluti, il codice speciale deve essere 'SpecialCode' o RESTITUIRE 999 viene colpito.

È possibile aggiungere un parametro @reallyReallyReallyDelete al sProc che servirà come misura di sicurezza. Se è impostato su YesYesYes effettivamente il commit della transazione

Si potrebbe utilizzare un ingresso chiamato @UserKnowsWhatTheyAreDoing bit e controllare per vedere se è vero prima di eseguire. Se è falsa, stampare un messaggio amichevole e tornare con grazia dalla procedura

La procedura può richiedere una discussione con un valore specifico, come 'Yes I know what I'm doing'. Oppure può cercare per una riga di un tavolo speciale con una conferma simile e un recente timestamp.

Ecco un altro approccio, che credo sia adatto per il caso particolare in cui una procedura deve essere chiamato da un utente direttamente piuttosto che da un'applicazione.

devo dire, si propone meno problemi per l'utente mentre più (forse, in modo sproporzionato) per lo sviluppatore in confronto con la maggior parte degli altri suggerimenti. Sarete voi a decidere se vi si addice.

In ogni caso, va qui.

In primo luogo, si crea una tabella speciale, CriticalCalls, per registrare le chiamate a procedure critiche. La tabella dovrebbe avere una struttura come questa:

SPID int,
ProcName sysname,
CallTime datetime

Fondamentalmente, l'idea è che un SP critico dovrebbe essere chiamato due volte: prima si registra la sua chiamata e informa l'utente di ripetere la chiamata entro un certo intervallo di tempo come una conferma della loro intenzione, e con la seconda chiamata, se fatta di conseguenza, si procede in realtà con il termine il suo compito.

Quindi, la parte iniziale di ogni procedura critica avrebbe questa logica:

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 */

In realtà, credo, sarebbe meglio utilizzare un SP dedicato (chiamato CheckCriticalCalls sotto) per tutte le manipolazioni con CriticalCalls, comprese tutte le modifiche necessarie. CheckCriticalCalls avrebbe ricevuto il nome della procedura da controllare e restituire una sorta di bandiera con se la procedura specificata deve svolgere la sua vera e propria operazione.

Quindi, potrebbe apparire un po 'come questo:

EXECUTE @result = CheckCriticalCalls 'ThisProcedureName';
IF @result = -1 BEGIN
  PRINT 'Call me again';
  RETURN;
END;

...  /* go on with the task */

L'idea alla base fissando il limite inferiore dell'intervallo è semplicemente quello di impedire all'utente di chiamare una procedura critica due volte automaticamente, ossia eseguendo due linee EXECUTE... identiche in un unico lotto. Il limite superiore, naturalmente, è necessario 1) assicurarsi che l'utente conferma la sua intenzione molto recente per eseguire l'operazione critica; 2) impedire l'esecuzione se il record esistente nella CriticalCalls è in realtà lasciato lì da una sessione passato con lo stesso SPID.

Quindi, in sostanza, un intervallo di 1-2 secondi a mezzo minuto sembrerebbe del tutto naturale per me. Si potrebbe scegliere invece figure diverse.

Avete bisogno di cancellarli VERAMENTE dal DB? Se mi posso permettere lo spazio in più ci metto una bandiera 'eliminato' nelle mie tabelle e un ultimo colonna aggiornata. In questo modo se un record viene eliminato accidentalmente almeno posso solito rintracciarlo e ripristinarlo abbastanza facilmente. Solo un pensiero.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top