SQL Server嵌套触发器

时间:2017-01-03 22:06:16

标签: sql sql-server triggers

我有三张桌子:

CREATE TABLE Rents
(
    RentID INT IDENTITY NOT NULL PRIMARY KEY,
    StartDate SMALLDATETIME,
    EndDate SMALLDATETIME,
    Price MONEY,
    RealEstateID INT UNIQUE NOT NULL,
    DealMadeByEmployeeID INT NOT NULL,

    CONSTRAINT CHK_Rents CHECK (Price > 0 AND EndDate > StartDate),
    CONSTRAINT FK_Rents_EstatesBasicInfo 
        FOREIGN KEY (RealEstateID) REFERENCES EstatesBasicInfo(RealEstateID),
    CONSTRAINT FK_Rents_Employees 
        FOREIGN KEY (DealMadeByEmployeeID) REFERENCES Employees(EmployeeID)
);

CREATE TABLE Purchases
(
    PurchaseID INT IDENTITY NOT NULL PRIMARY KEY,
    DateBought SMALLDATETIME,
    Price MONEY CHECK (Price>0),
    RealEstateID INT UNIQUE NOT NULL,
    DealMadeByEmployeeID INT NOT NULL,

    CONSTRAINT FK_Purchases_EstatesBasicInfo 
        FOREIGN KEY (RealEstateID) REFERENCES EstatesBasicInfo(RealEstateID),
    CONSTRAINT FK_Purchases_Employees 
        FOREIGN KEY (DealMadeByEmployeeID) REFERENCES Employees(EmployeeID)
);

CREATE TABLE EmployeesSalary
(
    EmployeeID INT NOT NULL PRIMARY KEY,
    CurrentSalary MONEY DEFAULT 0,-- на процент
    MonthlySalesMade INT DEFAULT 0,
    MonthlyRentsMade INT DEFAULT 0,

    CONSTRAINT FK_EmployeesSalary_Employees 
        FOREIGN KEY (EmployeeID) REFERENCES Employees(EmployeeID),
    CONSTRAINT CHK_EmployeesSalary 
        CHECK (CurrentSalary >= 0 AND MonthlySalesMade >= 0 AND MonthlyRentsMade >= 0)
);

每个人都有一个触发器

CREATE TRIGGER tr_EmployeesSalaryPurchasesUpdate --при INSERT в Purchases таблицата
ON Purchases
AFTER INSERT
AS
BEGIN
    UPDATE EmployeesSalary
    SET EmployeesSalary.MonthlySalesMade = EmployeesSalary.MonthlySalesMade + 1
    WHERE EmployeesSalary.EmployeeID IN (SELECT inserted.DealMadeByEmployeeID
                                         FROM inserted 
                                         WHERE DateBought IS NOT NULL)
END
                        --Update на MonthlyRentsMade
GO

CREATE TRIGGER tr_EmployeesSalaryRentsUpdate --при INSERT в Rents таблицата
ON Rents
AFTER INSERT
AS
BEGIN
    UPDATE EmployeesSalary
    SET MonthlyRentsMade = MonthlyRentsMade + 1
    WHERE EmployeesSalary.EmployeeID IN (SELECT inserted.DealMadeByEmployeeID 
                                         FROM inserted
                                         WHERE StartDate IS NOT NULL)
END

当我想向EmployeesSalary添加触发器时出现问题:

CREATE TRIGGER tr_EmployeesSalaryCurrentSalary
ON EmployeesSalary
AFTER INSERT
AS
BEGIN
    UPDATE EmployeesSalary
    SET CurrentSalary = CurrentSalary + ((MonthlySalesMade + MonthlyRentsMade) * 200)
    WHERE EmployeeID IN (SELECT i.EmployeeID 
                         FROM inserted AS i);
END

我希望当我在EmployeesSalary(通过其他两个触发器)获得插入时,CurrentSalary将被更新(取决于EmployeeID)。触发器会导致任何错误,但它不起作用。 (我认为这称为嵌套触发器不确定......)我的错误在哪里?

2 个答案:

答案 0 :(得分:0)

因为这是一个插入后触发器(在更新表上不会发生递归)。我认为你在哪里犯了一个错误就是在计算中使用NULL值所以我会尝试这个:

CREATE TRIGGER tr_EmployeesSalaryCurrentSalary
ON EmployeesSalary
AFTER INSERT
AS
BEGIN
UPDATE es
SET CurrentSalary = coalesce(i.CurrentSalary, 0) + ((coalesce(i.MonthlySalesMade, 0) + coalesce(i.MonthlyRentsMade, 0)) * 200)
from EmployeesSalary as es
inner join inserted AS i
on i.EmployeeID = es.EmployeeID
END

另外,我不喜欢IN语句,所以我加入了。

答案 1 :(得分:0)

我更喜欢使用计算列而不是像这样的触发器。这是一个例子。我还在两列中添加了ISNULL,以防你有一个NULL。否则计算将始终为NULL。

alter table EmployeesSalary
add ComputedSalary as CurrentSalary + ((isnull(MonthlySalesMade, 0) + isnull(MonthlyRentsMade, 0)) * 200) persisted