【问题标题】:Instead of insert trigger issue而不是插入触发器问题
【发布时间】:2019-09-17 14:37:25
【问题描述】:

我觉得我应该能够做到

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 表中插入数据。我想查看插入到 Books 表中的 ISBN 的书籍数量是否超过 BookInfo 中相同 ISBN 的 CopiesNo,抛出错误,否则插入带有打印消息“正在插入...”或其他内容的数据。

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

但我目前得到这个:

这是制作两个表(Books AND 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');

【问题讨论】:

  • 当我说“错误”时,它只是应该吐出一条错误消息,说它不起作用,但我在运行代码后添加了消息框所说的内容。
  • Dale,我尝试在顶部切换 SET 和 SELECT。我在上面的原始问题中留下了一个注释,以显示我做了什么。不过,我可能会误解你在说什么。
  • 我想我明白你现在的意思了。我最近刚刚更新了上面的代码,现在我得到了不同的消息输出。再次感谢您的意见!
  • 我认为@ISBN 是插入的值我猜...

标签: sql-server tsql triggers sql-insert


【解决方案1】:

我假设您试图阻止添加的 Book 记录多于相关 ISBNBookInfo 记录中配置的副本数。

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

如果您按照自己的逻辑解决此问题,则需要计算 Book 表和 Inserted 表中的 Book

但是,您可以通过使用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

【讨论】:

  • 我同意我没有考虑所有数字。我刚刚再次将我的代码更新为我目前正在处理的内容。我不确定你所拥有的正是我正在寻找的。我确实需要一个代替触发器。如果您可以查看我当前的代码并提出您的想法,我将不胜感激!
  • 为什么需要instead of 触发器?据我所知,您的代码正在尝试执行我的代码所做的事情,但是您的代码非常复杂并且还不能正常工作。与其继续修改代码,不如检查我在回答中描述的逻辑并澄清这一点。到目前为止,您所展示的任何内容都表明需要instead of 触发器。
  • 我目前正在按照您的方式进行操作。我只使用这个 INSTEAD OF 触发器在 Books 表中插入数据,因为这是我老师告诉我的。
猜你喜欢
  • 1970-01-01
  • 2022-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多