sql >> Database >  >> RDS >> Sqlserver

Wat moet ik doen als ik databasebeperkingen wil gebruiken, maar alleen als verwijderd wil markeren in plaats van verwijderen?

Je zou de id-waarde aan het einde van de naam kunnen toevoegen wanneer een record wordt verwijderd, dus als iemand id 3 verwijdert, wordt de naam Thingy3_3 en wanneer ze id 100 verwijderen, wordt de naam Thingy3_100. Hiermee kunt u een unieke samengestelde index maken voor de naam en verwijderde velden, maar u moet dan de naamkolom filteren wanneer u deze weergeeft en de id aan het einde van de naam verwijderen.

Misschien is een betere oplossing om uw verwijderde kolom te vervangen door een verwijderde_at-kolom van het type DATETIME. U zou dan een unieke index op naam en verwijderd op kunnen behouden, met een niet-verwijderd record met een null-waarde in het veld delete_at. Dit zou het aanmaken van meerdere namen in een actieve staat voorkomen, maar zou u in staat stellen om dezelfde naam meerdere keren te verwijderen.

U moet uiteraard een test doen bij het ongedaan maken van het verwijderen van een record om er zeker van te zijn dat er geen rij is met dezelfde naam en een leeg veld delete_at voordat u het verwijderen toestaat.

Je zou al deze logica in de database kunnen implementeren door een INSTEAD-OF-trigger te gebruiken voor het verwijderen. Deze trigger zou geen records verwijderen, maar zou in plaats daarvan de verwijderde_at-kolom bijwerken wanneer u een record verwijderde.

De volgende voorbeeldcode laat dit zien

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  

De selectie uit deze zoekopdracht geeft het volgende terug

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

Dus binnen uw code kunt u records verwijderen met een normale verwijdering en de trigger voor de details laten zorgen. Het enige mogelijke probleem (dat ik kon zien) was dat het verwijderen van reeds verwijderde records zou kunnen resulteren in dubbele rijen, vandaar de voorwaarde in de trigger om het veld delete_at op een reeds verwijderde rij niet bij te werken.



  1. Dynamische lengte in getalnotatie in to_number Oracle SQL

  2. Datumnotatie en verduidelijking van SQL-query

  3. Overschakelen van SQLite naar MySQL met Flask SQLAlchemy

  4. Geen gegevens meer om uit socketfout te lezen