SQL Trigger Recursive update - sql

I have an organizational database where in it each employee have a foreign key to it's boss(FID).
Table declaration:
Create Table Emp(
ID integer,
FID integer,
SALARY integer,
Primary key (ID),
foreign key (FID) references EMP
);
The following sql trigger should update the employees under a boss. And then update their children recursively. but it only updates one level.
CREATE TRIGGER SAL_TRIG ON EMP After UPDATE
as
declare #SALARY int
declare #OLDSAL int
declare #ID int
--use the 'inserted' keyword to access the values inserted into the invoice table
select #OLDSAL = Salary from deleted
select #SALARY = Salary from inserted
select #ID = ID from inserted
BEGIN
UPDATE EMP
SET SALARY = salary + #SALARY - #OLDSAL
WHERE FID = #ID
END
I want to know how to solve this problem.
Thank you.

Assuming this is SQL Server, you need to enable recursive triggers using sp_dboption. See MSDN for more details:
http://msdn.microsoft.com/en-us/library/ms189799.aspx

Related

DELETE statement conflicted with Reference constraints in SQL Stored Procedure

My Employee table has the Primary key Column that is (EmpID) which is referenced in two Other tables
EmployeeEducation table and EmployeeBankInformation table.
I want to Delete Employee against their ID but as I run the Stored Procedure my controller throws the error that the foreign key reference constraint conflicts because of the EmpID column.
ALTER PROCEDURE [dbo].[RemoveEmployee]
(
#EmpID int
)
AS
BEGIN
DELETE FROM Employee WHERE EmpID = #EmpID
DELETE FROM EmployeeEducation WHERE EmpID = #EmpID
DELETE FROM EmployeeBankInformation WHERE EmpID = #EmpID
END
Where am I going wrong? Can any of you tell what mistake I am making in my procedure?
You are very close, just need to remove the employee last:
ALTER PROCEDURE [dbo].[RemoveEmployee]
(
#EmpID int
)
AS
BEGIN
DELETE FROM EmployeeBankInformation WHERE EmpID = #EmpID
DELETE FROM EmployeeEducation WHERE EmpID = #EmpID
DELETE FROM Employee WHERE EmpID = #EmpID
END

SQL Inserted table trigger

If I run the following select statement inside an insert trigger, is it possible that it will return more than one result?:
DECLARE #variable char(1) = (SELECT ID FROM inserted)
If so, then what's the best to handle it?
Here is the problem that I am trying to solve: Every time when the new record is inserted into a table, I want to take the newly inserted ID and insert it into another table(if it doesn't exists).
Thank you!
Instead of
DECLARE #variable char(1) = (SELECT ID FROM inserted)
You can do something like following:
Declare #VarTempTbl as table (id int)
Insert into #VarTempTbl (id)
Select id from inserted
So that you can get those values for further processing
Now, I had created Two tables One for Master table and another for When any Insertion happens in that Master table, that entry has to inserted into the another table.
CREATE TABLE tblEmployee
(
Id int Primary Key,
Name nvarchar(30),
Gender nvarchar(10),
DepartmentId int
)
CREATE TABLE tblEmployee_New
(
Id int Primary Key,
Name nvarchar(30),
Gender nvarchar(10),
DepartmentId int
)
Trigger:
CREATE TRIGGER TR_EMPLOYEEDETAILS_AFTEROFINSERT
ON TBLEMPLOYEE
AFTER INSERT
AS
BEGIN
TRUNCATE TABLE tblEmployee_New
INSERT INTO TBLEMPLOYEE_NEW(ID, NAME, GENDER, DEPARTMENTID)
SELECT ID, NAME, GENDER, DEPARTMENTID
FROM INSERTED
END
Now Lets try to insert into record into a master table
Insert into tblEmployee values (1,'John', 'Male', 3)
Insert into tblEmployee values (2,'Mike', 'Male', 2)
It has automatically insert the newly inserted records into the another table.
If your want to remove the Previous records then add a drop Statement in that above Trigger.
Note: You can also use #Temp Table instead of creating a another table('tblEmployee_New')
Kinldy Share your comments

Handling bulk insert on a table with multiple input sources in SQL

I am performing bulk insert on a table in sql server 2012, at the same time i am picking the last inserted row with max() function and inserting it into another table , how to perform this when my table is getting data from multiple sources because while performing insertion into secondary table there is time delay while insertions are still happening in primary table so next time max() will pick up last updated row and i will loose some rows which are not max() but still inserted into primary table meanwhile.
create table dbo.emp
(
id int primary key identity(1,1),
emp_id int,
name varchar(255),
address varchar(255)
)
create table dbo.empx
(
id int primary key,
emp_id int foreign key references dbo.emp(id),
)
declare #temp int ;
set #temp=1;
while #temp<1000
begin
insert into dbo.emp(emp_id,name,address)values (100+#temp,'Ename'+LTRIM(STR(#temp)),'123 Sample Address'+LTRIM(STR(#temp)));
set #temp=#temp+1;
insert into dbo.empx select max(dbo.emp.id),max(dbo.emp.emp_id) from dbo.emp
end
Use OUTPUT Clause...
CREATE TABLE #empx
(Id INT ,emp_id VARCHAR(50))
DECLARE #temp INT ;
SET #temp=1;
WHILE #temp<1000
BEGIN
INSERT INTO dbo.emp(emp_id,name,address)
OUTPUT INSERTED.Id,INSERTED.emp_id INTO #empx(Id,emp_id)
VALUES (100+#temp,'Ename'+LTRIM(STR(#temp)),'123 Sample Address'+LTRIM(STR(#temp)));
SET #temp=#temp+1;
END
INSERT INTO dbo.empx(Id,emp_id)
SELECT Id,emp_id FROM #empx
Or Use a trigger
CREATE TRIGGER EmpLog
ON dbo.emp
AFTER Insert
AS
BEGIN
SET NOCOUNT ON;
Insert into dbo.empx (id,emp_id) Select id,emp_id from inserted;
END
GO

Oracle SQL: Invalid table name when creating a trigger

I created this 4 tables:
create table terminatedEmployees (
empid number primary key,
dept number,
empname varchar2(50),
salary number
);
create table employees (
empid number primary key,
dept number,
empname varchar2(50),
salary number
);
create table payroll (
empid number primary key,
salary number,
CONSTRAINT fk_payemploy
FOREIGN KEY (empid)
REFERENCES employees(empid)
);
create table salaryAudit (
empid number primary key,
oldsal number,
newsal number,
datechanged date,
changedby varchar2(25),
CONSTRAINT fk_salaryaudit
FOREIGN KEY (empid)
REFERENCES employees(empid)
);
and now I'm trying to create a trigger in order to update two of them when employees table is updated:
CREATE TRIGGER trigger_updated_employees
AFTER UPDATE ON employees
FOR EACH ROW
when (old.salary != new.salary)
BEGIN
UPDATE INTO salaryAudit (newsal, oldsal)
VALUES(:new.salary, :old.salary);
UPDATE INTO payroll (salary)
VALUES(:new.salary);
END;
But I'm getting the error:
2/5 PL/SQL: SQL Statement ignored
2/12 PL/SQL: ORA-00903: invalid table name
4/5 PL/SQL: SQL Statement ignored
4/12 PL/SQL: ORA-00903: invalid table name
The three tables I'm calling in the trigger are ok and other triggers I created work...
Try something like this:
CREATE TRIGGER TRIGGER_UPDATED_EMPLOYEES
AFTER UPDATE ON EMPLOYEES
FOR EACH ROW
WHEN (OLD.SALARY <> NEW.SALARY)
BEGIN
MERGE INTO PAYROLL p
USING (SELECT :NEW.EMPID AS EMPID FROM DUAL) d
ON (p.EMPID = d.EMPID)
WHEN NOT MATCHED THEN
INSERT (EMPID, SALARY)
VALUES (:NEW.EMPID, :NEW.SALARY)
WHEN MATCHED THEN
UPDATE
SET SALARY = :NEW.SALARY;
MERGE INTO SALARYAUDIT a
USING (SELECT :NEW.EMPID AS EMPID FROM DUAL) d
ON (a.EMPID = d.EMPID)
WHEN NOT MATCHED THEN
INSERT (EMPID, OLDSAL, NEWSAL, DATECHANGED, CHANGEDBY)
VALUES (:NEW.EMPID, :OLD.SALARY, :NEW.SALARY, SYSDATE, 'SOME_USER')
WHEN MATCHED THEN
UPDATE
SET OLDSAL = :OLD.SALARY,
NEWSAL = :NEW.SALARY,
DATECHANGED = SYSDATE,
CHANGEDBY = 'SOME_USER';
END TRIGGER_UPDATED_EMPLOYEES;
Share and enjoy.
I got it working just correcting the UPDATE statements syntax and modifying the condition as #BobJarvis suggested, this is the final result:
CREATE TRIGGER trigger_updated_employees
AFTER UPDATE OF salary ON employees
FOR EACH ROW
when (old.salary <> new.salary)
BEGIN
UPDATE salaryAudit
SET (newsal, oldsal)
VALUES (:new.salary, :old.salary)
WHERE (salaryAudit.empid = old.empid);
UPDATE payroll
SET (salary)
VALUES (:new.salary)
WHERE (payroll.empid = old.empid);
END;
The concept is the same that #BobJarvis proposed but a lot simpler. Thanks

Multi save data in a sub table base on primary table auto running number

I have 2 tables in SQL Server 2005
tblEmployee (Emp_No INT, Emp_Name NVARCHAR(50)
tblEducation (Edu_No INT, Edu_Name NVARCHAR(50), Emp_No)
Emp_No and Edu_No fields are auto increase number.
with relationship 1 to many
I want to create stored procedure to save data both tables in the same time.
Ex. Enter data
Emp_No Emp_Name
1 Jonh
Edu_No Edu_Name Emp_No
1 IT 1
2 Bussiness 1
3 Marketing 1
Please help. thanks.
If I understand you correctly, the following procedure will work:
CREATE PROCEDURE insert_both
AS
BEGIN
INSERT INTO tblEmployee(Emp_Name) VALUES('John')
DECLARE #emp_key int
SET #emp_key = SCOPE_IDENTITY()
INSERT INTO tblEducation(Edu_Name, Emp_No) VALUES('IT',#emp_key);
INSERT INTO tblEducation(Edu_Name, Emp_No) VALUES('Business',#emp_key);
INSERT INTO tblEducation(Edu_Name, Emp_No) VALUES('Marketing',#emp_key);
END
DECLARE #emID int
INERT INTO tblEmployee(Emp_Name) VALUES('NAME_OF_EM');
#emID = SCOPE_IDENTITY()
-- INSET Education
INERT INTO tblEducation (Edu_Name, Emp_No) VALUES('IT', emID );
INERT INTO tblEducation (Edu_Name, Emp_No) VALUES('Bussiness', emID );
You can get last auto increase number by SCOPE_IDENTITY().