如何在sql中添加删除约束

时间:2017-08-11 12:36:38

标签: sql sql-server constraints

我有书籍,书籍类别和类别的表格

看起来像这样

Book
    Id uniqueidentifier,
    Title varchar(255),
    Author varchar(255),
    Deleted datetime

BookCategory
    BookId
    CategoryId

Category
    Id uniqueidentifier
    Name varchar(255)
    Deleted datetime

我想编写一个约束,如果该图书的类别存在,则会阻止删除图书

意思是,如果一本书(比如说哈利波特)有一个虚构的类别,那么表BookCategory将同时包括Id' s of course。如果用户想要删除具有特定类别的图书,他将无法执行此操作。

some1可以帮助我吗?

PS 当我删除项目时,我实际上并没有删除它们,而是将属性删除为datetime。

4 个答案:

答案 0 :(得分:4)

在编辑之前,这是对原始问题的回答。

您正在寻找外键约束:

alter table BookCategory add constraint fk_BookCategory_Book
    foreign key (BookId) references Book(Id);

默认情况下,此类约束不允许您删除具有类别的图书。您可以了解cascading选项以提供更准确的行为。如果您不提供级联操作,则默认为ON DELETE NO ACTION,这意味着Book中的行不会被删除。

答案 1 :(得分:0)

如果我理解,您要做的是限制对表的更新以将记录标记为"已删除"。对表的约束不能这样做,但您可以通过更新触发器来完成此操作。此外,您应该尝试在您的应用程序中处理此逻辑。阅读与您类似的问题:Can an SQL constraint be used to prevent a particular value being changed when a condition holds?

答案 2 :(得分:0)

CREATE TABLE Book
(
    Id      UNIQUEIDENTIFIER
  , Title   VARCHAR(255)
  , Author  VARCHAR(255)
  , Deleted DATETIME
);

CREATE TABLE BookCategory
(
    BookId     UNIQUEIDENTIFIER
  , CategoryId UNIQUEIDENTIFIER
);

CREATE TABLE Category
(
    Id      UNIQUEIDENTIFIER
  , Name    VARCHAR(255)
  , Deleted DATETIME
);

INSERT INTO dbo.Book (   Id
                       , Title
                       , Author
                       , Deleted
                     )
VALUES (   'BCF8DE45-D26F-43EE-82CD-9975E35E51B1' -- Id - uniqueidentifier
         , 'Harry Potter'                         -- Title - varchar(255)
         , 'RK'                                   -- Author - varchar(255)
         , NULL                                   -- Deleted - datetime
       );

INSERT INTO dbo.Category (   Id
                           , Name
                           , Deleted
                         )
VALUES (   'EB6E823D-DFE8-448D-B648-EAE1EFE06358' -- Id - uniqueidentifier
         , 'Fantasy'                              -- Name - varchar(255)
         , NULL                                   -- Deleted - datetime
       );

INSERT INTO dbo.Category (   Id
                           , Name
                           , Deleted
                         )
VALUES (   '9B53C866-0DAA-4637-8169-5B8885A2E644' -- Id - uniqueidentifier
         , 'Category without books'               -- Name - varchar(255)
         , NULL                                   -- Deleted - datetime
       );

INSERT INTO dbo.BookCategory (   BookId
                               , CategoryId
                             )
VALUES (   'BCF8DE45-D26F-43EE-82CD-9975E35E51B1' -- BookId - int
         , 'EB6E823D-DFE8-448D-B648-EAE1EFE06358' -- CategoryId - int
       );
GO

CREATE TRIGGER trg_Category_Check_Category_Usage
ON Category
INSTEAD OF UPDATE
AS
    BEGIN
        IF UPDATE(Deleted)
            BEGIN
                IF EXISTS (   SELECT *
                                FROM INSERTED         i
                                JOIN dbo.BookCategory AS b ON b.CategoryId = i.Id
                               WHERE i.Deleted IS NOT NULL
                          )
                    THROW 60000, 'record exists', 1;
            END;

        UPDATE b
           SET b.deleted = i.deleted
             , b.Name = i.Name
          FROM Category b
          JOIN INSERTED i ON i.Id = b.Id;
    END;
GO
UPDATE dbo.Category SET Deleted = GETDATE()WHERE Name = 'Fantasy'; --error

UPDATE dbo.Category
   SET Deleted = GETDATE()
 WHERE Name = 'Category without books'; --no error

答案 3 :(得分:-2)

在表类别中为id创建一个主键,并使用外键将其与表bookcategory(categoryid)相关联。这将确保在不删除记录的同时不添加id而不引用父表类别从类别表中也可以。