php mysql database-design soft-delete

Prácticas recomendadas de eliminación suave(PHP/MySQL)



database-design soft-delete (6)

Problema

En una aplicación web que se ocupa de productos y pedidos, deseo mantener la información y las relaciones entre los antiguos empleados (usuarios) y las órdenes que manejan. Deseo mantener la información y las relaciones entre productos obsoletos y pedidos que incluyen estos productos.

Sin embargo, quiero que los empleados puedan desordenar las interfaces de administración, como eliminar antiguos empleados, productos obsoletos, grupos de productos obsoletos, etc.

Estoy pensando en implementar la eliminación suave. Entonces, ¿cómo uno generalmente hace esto?

Mis pensamientos inmediatos

Mi primer pensamiento es flag_softdeleted una flag_softdeleted " flag_softdeleted NOT NULL DEFAULT 0" en cada tabla de objetos que debe ser eliminable en forma continua. ¿O tal vez usar una marca de tiempo en su lugar?

Luego, proporciono un botón "Mostrar eliminado" o "Recuperar" en cada GUI relevante. Al hacer clic en este botón, incluirá registros borrados en el resultado. Cada registro eliminado tiene un botón "Restaurar". ¿Esto tiene sentido?

¿Tus pensamientos?

Además, agradecería cualquier enlace a recursos relevantes.


Así es como lo hago. Tengo un campo is_deleted que por defecto es 0. Luego las consultas solo WHERE is_deleted = 0 .

Intento alejarme de cualquier eliminación dura tanto como sea posible. A veces son necesarios, pero yo hago de eso una característica solo de administrador. De esa forma podemos eliminarlo, pero los usuarios no pueden ...

Editar: de hecho, podría usar esto para tener múltiples "capas" de eliminación suave en su aplicación. Entonces cada uno podría ser un código:

  • 0 -> No eliminado
  • 1 -> Suave eliminado, aparece en listas de elementos eliminados para usuarios de administración
  • 2 -> Borrado suave, no aparece para ningún usuario, excepto los usuarios administradores
  • 3 -> Solo aparece para los desarrolladores.

Tener los otros 2 niveles aún permitirá a los administradores y gerentes limpiar las listas eliminadas si son demasiado largas. Y dado que el código front-end simplemente comprueba is_deleted = 0 , es transparente para el frontend ...


El escenario más común que he encontrado es el que describes, una tinyint o incluso un bit representa un estado de IsActive o IsDeleted . Dependiendo de si esto se considera datos de "negocio" o de "persistencia", puede introducirse en la lógica de aplicación / dominio de la manera más transparente posible, como directamente en los procedimientos almacenados y el código de la aplicación no es conocido. Pero parece que esta es información comercial legítima para sus necesidades, por lo que debería conocerse en todo el código. (De modo que los usuarios pueden ver los registros eliminados, como usted sugiere).

Otro enfoque que he visto es usar una combinación de dos marcas de tiempo para mostrar una "ventana" de actividad para un registro dado. Hay un poco más de código para mantenerlo, pero el beneficio es que algo puede programarse para borrarse por sí mismo en un momento predeterminado. Los productos de tiempo limitado se pueden configurar de esa manera cuando se crean, por ejemplo. (Para que un registro esté activo indefinidamente, se puede usar un valor máximo (o simplemente una fecha futura absurdamente distante) o simplemente se puede null fecha de finalización si está de acuerdo con eso).

Luego, por supuesto, hay una mayor consideración de las cosas que se eliminan / recuperan de vez en cuando y el seguimiento de algún tipo de auditoría para eso. El enfoque de indicador solo conoce el estado actual, el enfoque de la marca de tiempo solo conoce la ventana más reciente. Pero cualquier cosa tan compleja como una pista de auditoría definitivamente debe almacenarse por separado que los registros en cuestión.


El uso de eliminaciones automáticas es algo común de implementar, y son útiles para muchas cosas, como:

  • Guardando el culo de un usuario cuando borraron algo
  • Guardando tu propio culo cuando borras algo
  • Mantenga un registro de lo que realmente sucedió (un tipo de auditoría)
  • etcétera

Hay una cosa que quiero señalar que casi todos fallan, y siempre vuelve para morderte en la parte trasera. Los usuarios de su aplicación no tienen la misma comprensión de una eliminación que usted.

Hay diferentes grados de eliminaciones. El usuario típico borra cosas cuando él (s)

  • Hizo un error y quiere eliminar los datos incorrectos
  • Ya no quiere ver nada en la pantalla

El problema es que si no registra la intención de la eliminación, su aplicación no puede distinguir entre datos erróneos (que nunca deberían haberse creado) y datos históricamente correctos.

Echa un vistazo a los siguientes datos:

PRICES | item | price | deleted | +------+-------+---------+ | A | 101 | 1 | | B | 110 | 1 | | C | 120 | 0 | +------+-------+---------+

Algunos usuarios no desean mostrar el precio del artículo B, ya que ya no venden ese artículo. Entonces él lo borra. Otro usuario creó un precio para el artículo A por un error, por lo que lo eliminó y creó el precio para el artículo C, como estaba previsto. Ahora, ¿me puede mostrar una lista de los precios de todos los productos? No, porque o bien tiene que mostrar los datos potencialmente erróneos (A), o tiene que excluir todos los precios, excepto los actuales (C).

Por supuesto, lo anterior se puede tratar de muchas maneras. Mi punto es que USTED debe ser muy claro con lo que USTED quiere decir con una eliminación, y asegurarse de que no haya manera de que los usuarios lo malinterpreten. Una forma sería obligar al usuario a elegir (ocultar / eliminar).


Si tuviera un código existente que coincida con esa tabla, agregaría la columna y cambiaría el nombre de la tabla. Luego crearía una vista con el mismo nombre que la tabla actual que selecciona solo los registros activos. De esa forma, ninguno de los códigos existentes se romperá y usted podría tener la columna de eliminación suave. Si desea ver el registro eliminado, seleccione desde la tabla base, de lo contrario, use la vista.


Siempre acabo de utilizar una columna eliminada como mencionaste. Realmente no hay mucho más que eso. En lugar de eliminar el registro, simplemente configure el campo eliminado en verdadero.

Algunos componentes que construyo permiten al usuario ver todos los registros eliminados y restaurarlos, otros solo muestran todos los registros donde deleted = 0


Su idea tiene sentido y se usa con frecuencia en la producción, pero, para implementarla, deberá actualizar bastante código para tener en cuenta el nuevo campo. Otra opción podría ser archivar (mover) los registros de "eliminación suave" en una tabla o base de datos separada. Esto se hace con frecuencia también y hace que el problema sea de mantenimiento en lugar de (re) programación. (Podría hacer que un desencadenante de tabla reaccione a la eliminación para archivar el registro eliminado).

Haría el archivo para evitar una actualización importante del código de producción. Pero si desea usar el campo de indicador borrado, úselo como una marca de tiempo para darle información útil adicional más allá de un booleano. (Nulo = no eliminado). Es posible que también desee agregar un campo DeletedBy para rastrear al usuario responsable de eliminar el registro. Usar dos campos te da mucha información que te dice quién borró qué y cuándo. (Las dos soluciones de campo adicionales también se pueden hacer en una tabla / base de datos de archivo).