CREATE TRIGGER T
ON TABLE_2
AFTER INSERT
AS
DECLARE @bought_t int,
@name_t varchar(20)
SELECT @name_t = name_t
FROM inserted
SELECT @bought_t = bought_t
FROM TABLE_1
WHERE name_t = @name_t
IF @bought_t < 100
BEGIN
UPDATE TABLE_1
SET bought_t = @bought_t + 1
WHERE TABLE_1.name_t = @name_t
END
ELSE
ROLLBACK TRANSACTION
我在'TABLE_2'中插入后发生更新的列(TABLE_1
)应该保持50到100之间的值。所以我问如果这个触发器是专业的,尽可能优化?或者我有一些可能导致错误/安全问题的缺陷。
答案 0 :(得分:1)
基本上,您需要将触发器完全重写为基于集合,并且能够在Inserted
伪表中使用多行。
幸运的是,这也让我更容易 - 在我看来 - 尝试这样的事情:
CREATE TRIGGER T
ON TABLE_2
AFTER INSERT
AS
UPDATE T1
SET bought_t = bought_t + 1
FROM TABLE_1 T1
INNER JOIN Inserted i ON i.name_t = T1.name_t
WHERE T1.bought_t < 100
更新:演示证明这有效:
-- create the two tables
CREATE TABLE TABLE_2 (ID INT NOT NULL IDENTITY(1,1), ProdName VARCHAR(50))
CREATE TABLE TABLE_1 (ProdName VARCHAR(50), Bought INT)
GO
-- create trigger on "TABLE_2" to update "TABLE_1"
CREATE TRIGGER T2Insert
ON TABLE_2
AFTER INSERT
AS
UPDATE T1
SET Bought = Bought + 1
FROM TABLE_1 T1
INNER JOIN Inserted i ON T1.ProdName = i.ProdName
WHERE T1.Bought < 100
GO
-- initialize TABLE_1 with some seed data
INSERT INTO dbo.TABLE_1 (ProdName, Bought)
VALUES ( 'Prod1', 0), ('Prod2', 20), ('Prod3', 40), ('Prod4', 40), ('Prod100', 100)
-- insert new values into TABLE_2
INSERT INTO dbo.TABLE_2 (ProdName)
VALUES ('Prod1'), ('Prod100'), ('Prod2'), ('Prod4')
-- get data to check
SELECT * FROM dbo.TABLE_1
这会呈现输出:
您可以很容易地看到:
Bought
Bought
更新#2:如果您需要一次插入多个相同的值,则需要稍微增强触发器,如下所示:
CREATE TRIGGER T2Insert
ON TABLE_2
AFTER INSERT
AS
-- declare table variable to hold names and update counts
DECLARE @UpdateCount TABLE (Name VARCHAR(50), UpdCount INT)
-- from the "Inserted" table, determine which names are being
-- inserted how many times using GROUP BY
INSERT INTO @UpdateCount (Name, UpdCount)
SELECT ProdName, COUNT(*)
FROM Inserted
GROUP BY ProdName
-- now join to this temporary table, and update as many times
-- as needed (instead of +1 for all cases)
UPDATE T1
SET Bought = Bought + uc.UpdCount
FROM TABLE_1 T1
INNER JOIN @UpdateCount uc ON uc.Name = T1.ProdName
WHERE T1.Bought < 100
GO