SQL Server触发,递归更新

时间:2015-12-22 13:05:28

标签: sql-server tsql recursion triggers

我有桌子员工,看起来像这样:

CREATE TABLE employees
(
     id int primary key,
     name varchar(20) not null,
     boss int references employees(id),
     salary money,
);

现在我必须创建一个触发器,在

之后
UPDATE employees
SET money = 5000 
WHERE id = 1

递归改变管理者的薪水(新旧薪水之间的差额为+500zł,UPDATE的员工有3名管理人员,所以我想更新他的经理薪水和工资,但每位经理都是他的经理的老板,所以我也要更新他们的工资。)

好吧,我已经写了触发器

CREATE TRIGGER salary_recursive ON employees
AFTER UPDATE
AS
  IF(SELECT salary FROM inserted)!=(SELECT salary FROM deleted)
  BEGIN
    declare @diff money = (SELECT salary FROM inserted) - (SELECT salary FROM deleted)
    update employees
    set salary = salary + @diff
    where boss = (SELECT id FROM inserted)
  END

它可以正常工作,但它只更新一个级别。所以我试过了

ALTER DATABASE myDatabase
SET RECURSIVE_TRIGGERS ON 

但它提出了

  

子查询返回的值超过1。当子查询遵循=,!=,<,< =,>,> =或子查询用作表达式时,不允许这样做。

我该如何解决?

1 个答案:

答案 0 :(得分:1)

问题在于此行和其他与

类似的行
IF (SELECT salary FROM inserted) != (SELECT salary FROM deleted)

如果SELECT返回多个值,则无效。您可以尝试按如下方式重写:

IF EXISTS (SELECT 1 FROM inserted i INNER JOIN deleted d ON d.id = i.id WHERE i.salary <> d.salary) BEGIN
    ...
END

块的内部也存在同样的问题。您实际上可以使用单个SQL语句解决此问题,但我现在无法对其进行测试。它可能会按照以下方式工作:

UPDATE employees
SET
    salary = salary + (SELECT i.salary - d.salary FROM inserted i INNER JOIN deleted d ON d.id = i.id WHERE i.ID = employees.boss)
WHERE
    boss in (SELECT i.id FROM inserted i INNER JOIN deleted d ON d.id = i.id WHERE d.salary <> i.salary)

这个想法是更新所有员工,其中boss-id是工资变化的ID之一。由于inserted中可能有多条记录,因此您需要在此使用in

更新会在工资字段中添加新旧值之间的差异,其中工资ID是当前记录的老板ID。