编写SQL Server触发器 - 错误

时间:2017-06-04 07:30:02

标签: sql-server tsql database-trigger

我有三张桌子:

  • Bus_Driver (drNo,drName,salary,StationNo,经验)

  • (StationNo,地址,地区,Salary_Commission)

  • 清洁(Cleaner_No,Cname,StationNo)

问题是要写一个触发器。它指出,如果公交车司机的工资比原来的工资增加了20%,那么增加值的0.05%将作为工资佣金转移到他的工作站。

我设法中途写入触发器,但是当我必须将金额转移到另一张桌子时卡住了。

我的代码是:

CREATE TRIGGER tr_1 
ON Bus_Driver
AFTER INSERT
AS
BEGIN
    DECLARE @salary MONEY
    SET @Salary = 0

    SELECT @Salary= salary 
    FROM Inserted
    WHERE @Salary > (120 / 100 * @Salary)

任何人都可以帮我解释如何编写后续步骤

2 个答案:

答案 0 :(得分:1)

你写的触发器是错误的。

首先,它是insert的触发器,而问题表明工资被提高,这意味着它应该是更新的触发器。

第二次,您的触发器假定插入的表中只有一行。但是,这种假设是错误的。 SQL服务器中的触发器是针对每个语句而不是每行触发的,这意味着插入(和删除)的表可能包含零行,一行或多行。

此问题的解决方案是编写更新触发器,然后更新站表。像这样:

CREATE TRIGGER tr_Bus_Driver_Update ON Bus_Driver
FOR UPDATE
AS

    UPDATE s
    SET Salary_Commission = Salary_Commission - 
                            (0.0005 * D.Salary) + -- Remove old salary of the driver(s) from salary_commition. 
                            (0.0005 * I.Salary) -- add new salary of the driver(s) to salary_commition
    FROM Station s
    INNER JOIN Inserted I ON s.StationNo = I.StationNo
    INNER JOIN Deleted D ON I.drNo = D.drNo -- assuming drNo is unique in Bus_Driver table
    WHERE I.Salary >= D.Salady * 1.2 -- You might need to cast to a floating point data type if the Salary is an integer data type

注意如果Salary是一个整数数据类型,只要在此触发器中使用它,您可能需要将工资转换为浮点数据类型。

答案 1 :(得分:0)

您需要从头开始停止并重新开始。

首先,您需要捕获AFTER UPDATE事件 - 而不是插入 - 因为您希望在更新薪水时执行某些操作(现有值替换为更高的值)。

其次,每个UPDATE语句将调用一次触发器,如果​​UPDATE影响多行,则DeletedInserted伪表将包含多行数据 - 所以你的SELECT @Salary = salary FROM Inserted语句注定失败 - 它将获取一个任意行并忽略可能也受影响的所有其他行。

UPDATE案例中,Inserted将具有新值(更新后),而Deleted具有旧值(更新前) - 所以这两个伪表之间的差异可以用来计算工资涨幅是否超过20%:

CREATE TRIGGER trBusDriverSalaryIncrease
ON dbo.Bus_Driver
AFTER UPDATE
AS
BEGIN
    -- declare a table variable to hold all revelant values
    DECLARE @RelevantIncreases TABLE (drNo INT, StationNo INT, SalaryIncrease DECIMAL(18,2))

    -- find those bus drivers who have had a more than 20% increase in their salary
    INSERT INTO @relevantIncreases (drNo, StationNo, SalaryIncrease)
        SELECT
            i.drNo, i.StationNo,    -- Driver and Station No
            (i.Salary - d.Salary)   -- Salary increase in absolute numbers
        FROM
            Deleted d
        INNER JOIN
            Inserted i ON d.drNo = i.drNo
        WHERE
            -- Salary increased by more than 20% 
            i.Salary > 1.2 * d.Salary

    -- now that we have all the relevant bus drivers and their salary increase
    -- insert this into the Station.Salary_Commission column
    UPDATE s
    SET Salary_Commission = s.Salary_Commission + ri.SalaryIncrease * 0.0005
    FROM dbo.Station s
    INNER JOIN @RelevantIncreases ri ON ri.StationNo = s.StationNo  
END