INSTEAD OF INSERT触发问题

时间:2019-04-28 23:28:41

标签: sql-server tsql sql-insert database-trigger

我觉得我应该能够

SET @InsertCount = COUNT (*) FROM INSERTED WHERE ISBN = @ISBN

但是它不会让我。我尝试使用SELECT语句来代替,因为我看到其他人在网上使用它,但是我不知道该怎么办。

IF OBJECT_ID ('BooksTrigger') IS NOT NULL
    DROP TRIGGER BooksTrigger
GO

-- create the trigger
CREATE TRIGGER BooksTrigger 
ON Books
INSTEAD OF INSERT
AS
    DECLARE @ISBN INT,
            @BookInDate DATE,
            @Memo VARCHAR(100),
            @Copies INT,
            @PreyQty INT,
            @InsertISBNCount INT,
            @CurrQty INT

    SET @InsertISBNCount = (SELECT COUNT(ISBN) FROM inserted WHERE ISBN = @ISBN)
    SET @PreyQty = (SELECT COUNT(ISBN) FROM Books WHERE ISBN = @ISBN)
    SET @CurrQty = (SELECT SUM(@InsertISBNCount + @PreyQty))
    SET @Copies = (SELECT CopiesNo FROM BookInfo WHERE ISBN = @ISBN)

    IF @Copies > @CurrQty
    BEGIN
        PRINT 'Inserting a copy of the book with ISBN ' + @ISBN

        INSERT INTO Books (ISBN, BookInDate, Memo)
        VALUES (@ISBN, @BookInDate, @Memo)
    END
    ELSE
        THROW 50027, 'Number of copies available for this book is less than the inserts for this book. Insert did not go through.', 1
GO

-- test
BEGIN TRY
    INSERT INTO Books 
    VALUES ('9780393248968', GETDATE(), 'test') --should print 'inserting'

    INSERT INTO Books 
    VALUES ('9780393248968', GETDATE(), 'test') --this one should throw an error as this would be the fifth book
END TRY
BEGIN CATCH
    PRINT ERROR_MESSAGE()
END CATCH

--see if the first one inserted
SELECT * FROM Books

因此,这里的目标是创建一个INSTEAD OF触发器,用于在Books表中插入数据。我想查看是否为同一ISBN在“图书”表中插入的图书数量大于在BookInfo中为同一ISBN所复制的图书数量,抛出错误,否则插入带有“插入...”之类的打印消息的数据。

我被告知完成后应该看到这样的消息:

Exprected Error Message

但是我现在正在得到这个:

Current Message

这是制作两个表(Books和BookInfo)的代码

--BookInfo Table
CREATE TABLE BookInfo
(
    ISBN BIGINT PRIMARY KEY CHECK (LEN([ISBN]) BETWEEN 10 AND 13),
    BookCategoryID INT,
    BookName VARCHAR(60),           
    BookAuthor VARCHAR(40),
    BookPublisher VARCHAR(40),
    BookPubDate DATE,
    BookPages INT CHECK (BookPages > 0),
    BookPrice INT CHECK (BookPrice > 0),
    CopiesNo INT DEFAULT 1 CHECK (CopiesNo > 0),
    Memo VARCHAR(100) NULL,
);

--Books Table
CREATE TABLE Books
(
    BookID INT PRIMARY KEY IDENTITY(1,1),
    ISBN BIGINT,
    BookInDate DATE,
    Memo VARCHAR(100) NULL, 
);
GO

ALTER TABLE Books
ADD FOREIGN KEY (ISBN) REFERENCES BookInfo(ISBN);
GO

INSERT INTO BookInfo (ISBN, BookCategoryID, BookName, BookAuthor,BookPublisher, BookPubDate, BookPages, BookPrice, CopiesNo, Memo)
VALUES (9780393248968, 1, 'Storm in a Teacup: The Physics of Everyday Life', 'Helen Czerski', 'W. W. Norton & Company', '01/10/2017', 288, 26.95, 4, 'On sale'),
       (9780062328502, 1, 'Dark Matter and the Dinosaurs: The Astounding', 'Lisa Randall', 'Ecco', '10/18/2016', 432, 17.99, 2, 'Not on Sale'),
       (9780262517263, 2, 'Grace Hopper and the Invention of the Information Age', 'Kurt Beyer', 'MIT Press', '02/01/2012', 404, 27.95, 2, 'On sale');

INSERT INTO Books (ISBN, BookInDate, Memo)
VALUES (9780393248968, '01/01/2018', 'this is a book'),
       (9780393248968, '01/01/2018', 'this is a book'),
       (9780393248968, '01/01/2018', 'this is a book'),
       (9780062328502, '01/02/2018', 'this is a book I think'),
       (9780062328502, '01/02/2018', 'this is a book I think'),
       (9780262517263, '01/03/2018', 'this is a book for sure'),
       (9780262517263, '01/03/2018', 'this is a book for sure');

1 个答案:

答案 0 :(得分:0)

我假设您要尝试阻止添加的Book记录数量超过相关BookInfo的{​​{1}}记录中配置的副本数。

但是,您的逻辑只是检查作为此插入语句的一部分插入的ISBN的数量(Book表仅用于此插入)。因此,如果只允许一本书的4份副本,但您将其作为3条记录插入,然后再插入3条记录(共6条记录),则触发器将允许这样做。

如果您遵循自己的逻辑来解决此问题,则需要计算inserted表和Book表中的Book

但是,您可以通过使用Inserted触发器,对after表进行计数,并在条件失败时回滚(例如,使用Book触发器),以更简单的方式解决问题。

create trigger BooksTrigger on Books
after Insert
as
begin
  -- if, for any BookInfo record, there exist more book records than CopiesNo, rollback
  if exists (select 1 from BookInfo BI where BI.CopiesNo < (select count(*) from Book B where B.ISBN = BI.ISBN)) begin
    ;THROW 50027, 'Number of copies available for this book is less than the inserts for this book. Insert did not go through.', 1
  end
end