编写 SQL 服务器触发器 - 错误
Writing a SQL Server trigger - error
我有三个table:
Bus_Driver (drNo,drName,salary,StationNo,experience)
站 (站号,地址,地区,Salary_Commission)
Cleaner (Cleaner_No, Cname, StationNo)
题目是写触发器。它表示如果公交车driver的工资比原来的工资增加了20%,那么增加的价值的0.05%将作为工资佣金转移到他的车站。
我写到一半触发了,但是当我要将金额转移到另一个时卡住了table。
我的代码是:
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)
谁能帮我写一下接下来的步骤
你写的触发器有误。
首先,它是insert的触发器,而问题是提高了薪水,意味着它应该是update的触发器。
Second,您的触发器假定插入的 table 中只有一行。然而,这个假设是错误的。 SQL 服务器中的触发器按语句触发,而不是按行触发,这意味着插入(和删除)table 可能包含零、一或多行。
这个问题的一个解决方案是编写更新触发器,然后更新站点 table。像这样:
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
注意如果在此触发器中使用的薪水是整数数据类型,则可能需要将薪水转换为浮点数据类型。
你需要停下来,重新开始。
首先,您需要捕获 AFTER UPDATE
事件 - 而不是插入 - 因为您想在薪水更新时执行某些操作(现有值被更高的值替换)。
其次,每个 UPDATE
语句将调用一次触发器,如果 UPDATE
影响多行,则 Deleted
和 Inserted
伪表将包含多行数据 - 所以你的 SELECT @Salary = salary FROM Inserted
语句注定失败 - 它将获取任意一行并忽略所有其他可能也会受到影响的行。
在 UPDATE
情况下,Inserted
将具有 新值(更新后),而 Deleted
具有 old values(更新前)-因此可以通过这两个伪表之间的差异来计算工资增长是否超过 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
我有三个table:
Bus_Driver (drNo,drName,salary,StationNo,experience)
站 (站号,地址,地区,Salary_Commission)
Cleaner (Cleaner_No, Cname, StationNo)
题目是写触发器。它表示如果公交车driver的工资比原来的工资增加了20%,那么增加的价值的0.05%将作为工资佣金转移到他的车站。
我写到一半触发了,但是当我要将金额转移到另一个时卡住了table。
我的代码是:
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)
谁能帮我写一下接下来的步骤
你写的触发器有误。
首先,它是insert的触发器,而问题是提高了薪水,意味着它应该是update的触发器。
Second,您的触发器假定插入的 table 中只有一行。然而,这个假设是错误的。 SQL 服务器中的触发器按语句触发,而不是按行触发,这意味着插入(和删除)table 可能包含零、一或多行。
这个问题的一个解决方案是编写更新触发器,然后更新站点 table。像这样:
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
注意如果在此触发器中使用的薪水是整数数据类型,则可能需要将薪水转换为浮点数据类型。
你需要停下来,重新开始。
首先,您需要捕获 AFTER UPDATE
事件 - 而不是插入 - 因为您想在薪水更新时执行某些操作(现有值被更高的值替换)。
其次,每个 UPDATE
语句将调用一次触发器,如果 UPDATE
影响多行,则 Deleted
和 Inserted
伪表将包含多行数据 - 所以你的 SELECT @Salary = salary FROM Inserted
语句注定失败 - 它将获取任意一行并忽略所有其他可能也会受到影响的行。
在 UPDATE
情况下,Inserted
将具有 新值(更新后),而 Deleted
具有 old values(更新前)-因此可以通过这两个伪表之间的差异来计算工资增长是否超过 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