Pregunta

Tengo un procedimiento almacenado que está haciendo una gran cantidad de borrado. Cientos de miles de registros. No va a ser ejecutable de la aplicación, pero aún así, a mí respecta, que uno de mis clientes accidentalmente lo ejecuta (tuve problemas anteriores debido a su "curiosidad"): D

Sí. existen copias de seguridad y cosas por el estilo, pero estaba pensando .... no asustarlos ... ¿hay una manera de pedir al usuario "¿está seguro?" antes de ejecutarlo? :) gracias

¿Fue útil?

Solución

Creo que se puede tener un parámetro llamado "confirmación" que requiere una cadena específica (e, g, "Yo sé lo que estoy haciendo") para ser aprobada en, si no se establece, o se establece de forma incorrecta, simplemente volver a partir del procedimiento sin ejecutar el código principal. No es exactamente lo que quería, pero es una opción.

por ejemplo, - (sintaxis y probablemente no probado horrible)

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

Otros consejos

En resumen, no.

La teoría es que cualquiera con permisos para encontrar y ser capaz de ejecutar un procedimiento almacenado, debe permitirse. Sería mejor para restringir permisos para que los que tienen un exceso curiosidad no tienen los permisos para ejecutar esto.

El otro menos seguro, una opción sería exigir un secreto predefinido que debe pasar como un 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 es exigible, ¿por qué incluirlo? Después de todo, cuando se llega a hacer las tareas de tipo de administrador, puede hacer que las declaraciones de secuencias de comandos fuera como un archivo que se puede mantener segura en su propia máquina

utilizar un enfoque dual de múltiples niveles:

1) control de ejecución de 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) puso un gran llamativo comentario en el inicio 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 RETURN 999 es exitosa.

Puede agregar un parámetro @reallyReallyReallyDelete a la sproc que servirá como medida de seguridad:. Si se establece a YesYesYes realmente confirmar la transacción

Se podría utilizar una entrada de llamada @UserKnowsWhatTheyAreDoing poco y comprobar para ver si es verdad antes de ejecutar. Si es falso, imprimir un mensaje amable y devolver gracia del procedimiento

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

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

Debo decir, que propone menos problemas para el usuario, mientras que más (tal vez, de manera desproporcionada) para el desarrollador en comparación con la mayoría de otras sugerencias. A decidir si le conviene.

De todos modos, aquí va.

En primer lugar, se crea una mesa especial, CriticalCalls, para registrar las 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, como una confirmación de su intención, y con la segunda llamada, si hecha por consiguiente, que 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 ha comprobado y devolver un tipo de indicador que muestra si el procedimiento especificado debe llevar a cabo su funcionamiento real.

Por lo que podría parecer algo como esto:

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

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

La idea detrás 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 líneas EXECUTE... idénticos en un solo lote. El límite superior, por supuesto, es necesario 1) asegurarse de que el usuario confirma su intención muy reciente para realizar la operación crítica; 2) evitar la ejecución si el registro existente en CriticalCalls es en realidad dejó allí de una sesión pasado con el mismo SPID.

Así que, básicamente, un intervalo de 1-2 segundos a medio minuto parecería muy natural para mí. Es posible elegir diferentes figuras en su lugar.

¿Necesita eliminar realmente los de la BD? Si me puedo permitir el espacio extra que voy a poner una bandera 'eliminados' en mis tablas y una última columna actualizada. De esta manera, si se elimina un registro accidentalmente al menos por lo general puede seguir hacia abajo y restaurarlo con bastante facilidad. Es sólo una idea.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top