我尝试创建一个触发器来将在我的Food
表上完成的数据操作存储在另一个称为FoodTriggerTable
的表中。当我仅插入一行数据时,我可以在FoodTriggerTable
中很好地记录数据操作。但是,一次插入多行时,仅存储第一行数据的信息。我有以下触发器:
CREATE TRIGGER InsertFoodTrigger ON Food
AFTER INSERT
AS
DECLARE @FoodID varchar(5);
DECLARE @FoodName nvarchar(50);
DECLARE @FoodDesc nvarchar(200);
DECLARE @FoodPrice money;
DECLARE @InsertAction varchar(200);
DECLARE @InsertActionTime datetime;
DECLARE @Amount int;
SELECT @FoodID = i.FoodID FROM INSERTED i;
SELECT @FoodName = i.FoodName FROM INSERTED i;
SELECT @FoodDesc = i.FoodDesc FROM INSERTED i;
SELECT @FoodPrice = i.FoodPrice FROM INSERTED i;
SELECT @Amount = COUNT(*) FROM INSERTED i;
SET @InsertAction = 'You''ve inserted ' + CONVERT(varchar(10), @Amount) + ' data into ''Food'' table';
INSERT INTO FoodTriggerTable (FoodID, FoodName, FoodDesc, FoodPrice, InsertAction, InsertActionTime)
VALUES (@FoodID, @FoodName, @FoodDesc, @FoodPrice, @InsertAction, GETDATE());
GO
然后我尝试了以下INSERT
:
INSERT INTO Food
VALUES ('CH006', 'Dummy Data 1', 'Dummy data', '0', '34'),
('CH007', 'Dummy Data 2', 'Dummy data', '0', '75');
如何修复触发器,使其同时记录第二行数据操作?
答案 0 :(得分:3)
您需要考虑基于集合的情况-插入的是一个表,每个插入或更新的记录都有一行。就像使用普通表一样使用它-不要尝试将其转换为函数式编程,例如
INSERT INTO FoodTriggerTable (FoodID, FoodName, FoodDesc, FoodPrice, InsertAction, InsertActionTime)
select FoodId, FoodName, FoodDesc, FoodPrice, null, getdate()
from Inserted
注意:现在每行1个时,不确定要使用哪个InsertAction-由您决定。
编辑:程序实际上是正确的术语。在使用T-SQL进行操作时,通常会操纵数据集,这是它设计的目的,因为它具有数据库编程语言。因此,通常您会尝试根据数据集来框架化并解决您要解决的问题。在编写触发器时,这非常明显,因为插入和更新/删除可能涉及任意数量的记录,因此您必须处理该记录。当然,您可以使用游标和循环来回退到过程编程,但是性能会受到影响,我想它并不是这样做的方法:)有很多文章,这里有一个示例https://www.sqlshack.com/introduction-set-based-vs-procedural-programming-approaches-t-sql/
答案 1 :(得分:1)
CREATE TRIGGER InsertFoodTrigger ON Food
AFTER INSERT
AS
INSERT INTO FoodTriggerTable (FoodID, FoodName, FoodDesc, FoodPrice, InsertAction, InsertActionTime)
SELECT FoodID, FoodName, FoodDesc, FoodPrice, 'You''ve inserted ' + CONVERT(varchar(10), (SELECT COUNT(*) FROM inserted)) + ' data into ''Food'' table', GETDATE()
FROM inserted
GO