sql >> Base de Datos >  >> RDS >> Sqlserver

¿Qué hacer cuando quiero usar las restricciones de la base de datos pero solo marcar como eliminado en lugar de eliminar?

Puede agregar el valor de identificación al final del nombre cuando se elimina un registro, por lo que cuando alguien elimina la identificación 3, el nombre se convierte en Thingy3_3 y luego, cuando elimina la identificación 100, el nombre se convierte en Thingy3_100. Esto le permitiría crear un índice compuesto único en el nombre y los campos eliminados, pero luego debe filtrar la columna de nombre cada vez que la muestre y eliminar la identificación del final del nombre.

Quizás una mejor solución sería reemplazar su columna eliminada con una columna delete_at de tipo DATETIME. Luego, podría mantener un índice único en el nombre y eliminarlo en, con un registro no eliminado que tenga un valor nulo en el campo delete_at. Esto evitaría la creación de varios nombres en un estado activo, pero le permitiría eliminar el mismo nombre varias veces.

Obviamente, debe hacer una prueba al recuperar un registro para asegurarse de que no haya una fila con el mismo nombre y un campo delete_at nulo antes de permitir la recuperación.

De hecho, podría implementar toda esta lógica dentro de la base de datos utilizando un activador INSTEAD-OF para la eliminación. Este activador no eliminaría registros, sino que actualizaría la columna delete_at cuando eliminara un registro.

El siguiente código de ejemplo demuestra esto

CREATE TABLE swtest (  
    id          INT IDENTITY,  
    name        NVARCHAR(20),  
    deleted_at  DATETIME  
)  
GO  
CREATE TRIGGER tr_swtest_delete ON swtest  
INSTEAD OF DELETE  
AS  
BEGIN  
    UPDATE swtest SET deleted_at = getDate()  
    WHERE id IN (SELECT deleted.id FROM deleted)
    AND deleted_at IS NULL      -- Required to prevent duplicates when deleting already deleted records  
END  
GO  

CREATE UNIQUE INDEX ix_swtest1 ON swtest(name, deleted_at)  

INSERT INTO swtest (name) VALUES ('Thingy1')  
INSERT INTO swtest (name) VALUES ('Thingy2')  
DELETE FROM swtest WHERE id = SCOPE_IDENTITY()  
INSERT INTO swtest (name) VALUES ('Thingy2')  
DELETE FROM swtest WHERE id = SCOPE_IDENTITY()  
INSERT INTO swtest (name) VALUES ('Thingy2')  

SELECT * FROM swtest  
DROP TABLE swtest  

La selección de esta consulta devuelve lo siguiente

id      name       deleted_at
1       Thingy1    NULL
2       Thingy2    2009-04-21 08:55:38.180
3       Thingy2    2009-04-21 08:55:38.307
4       Thingy2    NULL

Entonces, dentro de su código, puede eliminar registros usando una eliminación normal y dejar que el disparador se encargue de los detalles. El único problema posible (que pude ver) era que eliminar registros ya eliminados podría dar como resultado filas duplicadas, por lo tanto, la condición en el disparador para no actualizar el campo delete_at en una fila ya eliminada.