Reputation: 169
I have the table employees, which looks like this:
CREATE TABLE employees
(
id int primary key,
name varchar(20) not null,
boss int references employees(id),
salary money,
);
Now I have to create a trigger, which after
UPDATE employees
SET money = 5000
WHERE id = 1
change recursively managers' salary (difference between old and new salary amount to +500zł, employee from the UPDATE has 3 manages, so I want to update his salary and salaries of his managers, but every manager is a boss for his managers, so I want to update their salaries too.)
So ok, I've written the trigger
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
It works correctly, but it updates only one level. So I've tried
ALTER DATABASE myDatabase
SET RECURSIVE_TRIGGERS ON
but it raises
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
How can I fix it?
Upvotes: 2
Views: 565
Reputation: 56717
The problem is in this line and other lines that are similar to
IF (SELECT salary FROM inserted) != (SELECT salary FROM deleted)
This will not work if the SELECT
returns more than one value. You could try to rewrite this as follows:
IF EXISTS (SELECT 1 FROM inserted i INNER JOIN deleted d ON d.id = i.id WHERE i.salary <> d.salary) BEGIN
...
END
The inner part of your block also has the same problem. You can actually solve this using a single SQL statement, but I can not test it right now. It might work along the lines of this:
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)
The idea is to update all the employees where the boss-id is one of the ids where the salary has changed. As there can be more than one record in inserted
, you need to use in
here.
The update adds to the salary field the difference between the new and old values where the salary id is the current record's boss-id.
Upvotes: 2