¿Hay un “¿estás seguro” para la ejecución del procedimiento almacenado? :)
-
23-09-2019 - |
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
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.