2010-03-29 9 views
6

Tengo un procedimiento almacenado que está haciendo una gran cantidad de eliminar. Cientos de miles de registros. No se podrá ejecutar desde la aplicación, pero aún así, me preocupa que uno de mis clientes lo ejecute accidentalmente (tuve problemas antes debido a su "curiosidad"): D¿Existe un "estoy seguro" para la ejecución del procedimiento almacenado? :)

Sí. hay copias de seguridad y cosas así, pero estaba pensando ... no asustarlos ... ¿hay alguna manera de preguntarle al usuario "¿estás seguro?" antes de ejecutarlo? :) gracias

+10

¿Por qué no configura permisos para sus procs almacenados? De esta forma, solo los usuarios autorizados pueden ejecutarlo. –

+0

@ The Elite Gentleman: No estoy diciendo que los usuarios autorizados a veces deseen sentirse como seres humanos en lugar de máquinas. Este caso particular muestra más bien que a algunos desarrolladores no les importa percibir a los usuarios como meros mortales. :) –

Respuesta

7

Supongo que podría tener un parámetro llamado "confirmación" que requiere una cadena específica (e, g, "sé lo que estoy haciendo") para pasar, si no está configurado, o está configurado incorrectamente, simplemente regrese del procedimiento sin ejecutar el código principal. No es exactamente lo que querías, pero es una opción.

por ejemplo - (sintaxis no probado y probablemente 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 
+0

Podría funcionar, pero creo que se convertirá rápidamente en un "Parámetro copiar y pegar e ignorar" –

+4

De acuerdo, pero no hay nada que impida que eviten cualquier cosa si tienen acceso al sproc directamente de todos modos. Es mucho mejor agregar seguridad de acceso/ejecución apropiada alrededor de todo. – ZombieSheep

+0

+1 Estoy totalmente de acuerdo, esta es una cuestión de disciplina –

6

En resumen, no.

La teoría dice que cualquier persona con permisos para encontrar y poder ejecutar un procedimiento almacenado, debe estar permitido. Sería mejor restringir los permisos para que aquellos con un exceso de curiosidad no tengan los permisos para ejecutar esto.

El otro, menos seguro, la opción sería exigir un secreto predefinido que necesita ser pasado como parámetro - por supuesto que podría simplemente guión el procedimiento almacenado en camino para encontrar el secreto aunque ...

Por supuesto, el otro punto sería: si no se puede llamar, ¿por qué incluirlo? Después de todo, cuando realiza tareas de tipo administrativo, puede generar las secuencias de comandos como un archivo que puede mantener seguro en su propia máquina

1

Puede usar una entrada de bit llamada @UserKnowsWhatTheyAreDoing y verificar si es verdadero antes de ejecutar. Si es falso, imprima un mensaje amistoso y regrese con gracia del procedimiento

2

Puede agregar un parámetro @reallyReallyReallyDelete al sproc que servirá como medida de seguridad: si se establece en YesYesYes, se comprometerá la transacción.

1

El procedimiento puede requerir un argumento con un valor específico, como 'Yes I know what I'm doing'. O puede buscar una fila y una tabla especial con una confirmación similar y una marca de tiempo reciente.

3

utilizar un enfoque doble de varios niveles:

1) control de ejecución de la seguridad, como:

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

2) utilizar un nombre de procedimiento muy descriptiva/miedo, como

CREATE PROCEDURE Will_Delete_All_Your_Data ... 

3) poner un comentario llamativo grande al comienzo del procedimiento almacenado

--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) hacer pasar el usuario en un código de acceso especial ofuscado:

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

Para su información, el código especial debe ser "SpecialCode o su retorno 999 es golpeado.

0

¿Necesita REALMENTE eliminarlos de la base de datos? Si puedo pagar el espacio extra, pondré una bandera 'Eliminada' en mis tablas y una última columna actualizada. De esta forma, si un registro se borra accidentalmente, al menos generalmente puedo rastrearlo y restaurarlo con bastante facilidad. Solo un pensamiento.

1

Aquí hay otro enfoque, que creo que es adecuado para el caso particular cuando un procedimiento debe ser llamado por un usuario directamente en lugar de desde una aplicación.

Debo decir que propone menos problemas para el usuario y más (quizás, desproporcionadamente) para el desarrollador en comparación con la mayoría de las otras sugerencias. Tú decides si te conviene.

De todos modos, aquí va.

Primero, cree una tabla especial, CriticalCalls, para registrar llamadas a procedimientos críticos. La tabla tendría una estructura como esta:

SPID int, 
ProcName sysname, 
CallTime datetime 

Básicamente, la idea es que un SP crítica debe ser llamado dos veces: primero se registra su llamada e informa al usuario que repita la llamada dentro de un cierto intervalo de tiempo que una confirmación de su intención, y con la segunda llamada, si se realiza en consecuencia, en realidad procede a completar su tarea.

Así que la parte inicial de cada procedimiento crítico tendría esta lógica:

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 realidad, creo, sería mejor utilizar un SP específico (llamado CheckCriticalCalls abajo) para todas las manipulaciones con CriticalCalls, incluyendo todas las modificaciones necesarias. CheckCriticalCalls recibiría el nombre del procedimiento que se comprobará y devolverá un tipo de indicador que muestra si el procedimiento especificado debe realizar su operación real.

lo tanto, podría parecer algo así como esto:

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

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

La idea de establecer el límite inferior del intervalo es simplemente para evitar que el usuario llama a un procedimiento crítico dos veces de forma automática, es decir, mediante la ejecución de dos idénticos EXECUTE... líneas en un lote El límite superior, por supuesto, es necesario para 1) garantizar que el usuario confirme su intención muy reciente de realizar la operación crítica; 2) evitar la ejecución si el registro existente en CriticalCalls se deja allí desde una sesión pasada con el mismo SPID.

Así que, básicamente, un intervalo de 1-2 segundos a medio minuto me parecería bastante natural. Puede elegir diferentes figuras en su lugar.

Cuestiones relacionadas