What to do when I want to use database constraints but only mark as deleted instead of deleting?

后端 未结 10 990
野的像风
野的像风 2020-12-31 20:55

I am working in a project where database items are not deleted, but only marked as deleted. Something like this:

id   name     deleted
---  -------  --------         


        
相关标签:
10条回答
  • 2020-12-31 21:38

    For a simple table called [Test] with columns ID(int), Filter(nvarchar), Deleted(bit)

    ALTER TABLE [dbo].[Test] ADD 
        CONSTRAINT [DF_Test_Deleted] DEFAULT (0) FOR [Deleted],
        CONSTRAINT [IX_Test] UNIQUE  NONCLUSTERED 
        (
            [filter],
            [Deleted]
        )  ON [PRIMARY] 
    
    0 讨论(0)
  • 2020-12-31 21:38

    The type of constraint you require is a table-level CHECK constraint i.e. a CHECK constraint consisting of a subquery which tests NOT EXISTS (or equivalent) for the table e.g.

    CREATE TABLE Test 
    (
       ID INTEGER NOT NULL UNIQUE, 
       name VARCHAR(30) NOT NULL, 
       deleted INTEGER NOT NULL, 
       CHECK (deleted IN (0, 1))
    );
    
    ALTER TABLE Test ADD
       CONSTRAINT test1__unique_non_deleted
          CHECK 
          (
             NOT EXISTS 
             (
                SELECT T1.name
                  FROM Test AS T1
                 WHERE T1.deleted = 0
                 GROUP
                    BY T1.Name
                HAVING COUNT(*) > 1
             )
          );
    
    INSERT INTO Test (ID, name, deleted) VALUES (1, 'Thingy1', 0)
    ;
    INSERT INTO Test (ID, name, deleted) VALUES (2, 'Thingy2', 0)
    ;
    INSERT INTO Test (ID, name, deleted) VALUES (3, 'Thingy3', 1)
    ;
    INSERT INTO Test (ID, name, deleted) VALUES (4, 'Thingy3', 1)
    ;
    INSERT INTO Test (ID, name, deleted) VALUES (5, 'Thingy3', 0)
    ;
    INSERT INTO Test (ID, name, deleted) VALUES (6, 'Thingy3', 0)
    ;
    

    The last INSERT (ID = 6) will cause the constraint to bite and the INSERT will fail. Q.E.D.

    ...ooh, nearly forgot to mention: SQL Server doesn't yet support CHECK constraints with that contain a subquery (I tested the above on ACE/JET, a.k.a. ). While you could use a FUNCTION I've read this is unsafe due to SQL Server testing constraints on a row-by-row basis (see David Portas' Blog). Until this full SQL-92 feature is supported in SQL Server, my preferred workaround is to use the same logic in a trigger.

    0 讨论(0)
  • 2020-12-31 21:39

    Not sure about SQLServer2005, but you can define compound constrainst/indexes

    CREATE UNIQUE INDEX [MyINDEX] ON [TABLENAME] ([NAME] , [DELETED])
    

    As pointed out by SteveWeet, this will only allow you to delete/create twice.

    0 讨论(0)
  • 2020-12-31 21:41

    It might be worth considering using a "recycle bin" table. Instead of keeping the old records in the same table with a flag, move them to its own table with its own constraints. For instance, in the active table you do have a UNIQUE constraint on name, but in the recycle bin table you don't.

    0 讨论(0)
提交回复
热议问题