As the title states, I'm trying to use a trigger to update a value in Table2 when a row gets deleted from Table1. My code looks like this:
CREATE TRIGGER TRG_Table1_DEL
ON Table1
FOR DELETE
AS
UPDATE Table2 SET
FK_Table1ID = NULL
WHERE FK_Table1ID = (SELECT Table1ID FROM DELETED)
The first error I get is with the UPDATE command and that states:
"Incorrect syntax near 'UPDATE'. Expecting EXTERNAL.
The second error
is with the DELETED table that I'm trying to access. This states
"Invalid object name 'DELETED'.
Overall, I'm just trying to mimic a constraint that sets the column to null (ON DELETE SET NULL). I'm doing this because I got an error saying I might cause multiple cycles or cascade paths when trying to add the constraint.
For my code, I based it off this answer.
This should work in SQL Server. I have just replaced (=) with (in).
CREATE TRIGGER TRG_Table1_DEL
ON Table1
FOR DELETE
AS
UPDATE Table2
SET FK_Table1ID = NULL
WHERE FK_Table1ID IN (SELECT Table1ID FROM DELETED)
Example:
create table empsalary(empid int, month int , salary int);
insert into empsalary values(1, 1, 100);
insert into empsalary values(1, 2, 101);
insert into empsalary values(1, 3, 103);
create table emp(empid int, id int);
insert into emp values(1,1);
CREATE TRIGGER TRG_Table1_DEL
ON empsalary
FOR DELETE
AS
UPDATE emp
SET id = NULL
WHERE empid IN (SELECT empid FROM DELETED)
select * from empsalary
empid
month
salary
1
1
100
1
2
101
1
3
103
select * from emp
empid
id
1
1
delete empsalary where month=1;
select * from empsalary;
empid
month
salary
1
2
101
1
3
103
select *from emp;
empid
id
1
null
db<>fiddle here
The problem turned out to have a very simple fix. I was getting the errors because I was trying to add the trigger after dropping a constraint. This is fine, but I forgot to add a GO command in between the dropping of the constraint and the creation of the trigger. My code looked like this:
DROP CONSTRAINT
ADD TRIGGER
but this was the correct solution:
DROP CONSTRAINT
GO
ADD TRIGGER
Edit: as DaleK has pointed out, I also need to modify the WHERE clause in case the DELETED table has multiple rows
Related
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
This question has already been asked several times but the solution is not working for me. I don't know why.
Actually i am trying to create a temp table in sql query where i am inserting some records in temp table using select into but everytime it returns empty row:
here is what i am trying:
Create Table #TempTable
(
EntityID BIGINT
)
INSERT INTO #TempTable (EntityID)
SELECT pkEntityID FROM Employee WHERE EmpID = 45
Select * from #TempTable
Corresponding to 45 , there are 10 rows in Employee table. IS it like I have to do something else or a loop like structure here as we can only insert one row in a table at once?
This has been stated in the comments, all of which i up-voted, but to answer your question... there isn't anything else you have to do. There clearly isn't an EmpID = 45 in your source table. Here's a reproducible example:
Declare #Employee Table (pkEntityID bigint, EmpID int)
insert into #Employee (pkEntityID, EmpID)
values
(32168123,45),
(89746541,45),
(55566331,45),
(45649224,12)
Create Table #TempTable
(
EntityID BIGINT
)
INSERT INTO #TempTable (EntityID)
SELECT pkEntityID FROM #Employee WHERE EmpID = 45
Select * from #TempTable
drop table #TempTable
Have you accidentally also created the Employee table in the master database and you are currently connected to the master database?
I'm having a table like this
Create table test1(emp_id decimal(5,0), emp_name varchar(20));
Insert into test1(2015,'XYZ');
Insert into test1(2016,'XYZ2');
Now I want to update emp_id to row_number()
or
add new column into same table like (emp_no integer) to row_number().
can anyone please tell me the query for this?
You need to use UPDATE FROM:
UPDATE test1
FROM
( SELECT ROW_NUMBER() OVER (ORDER BY emp_id) AS rn,
emp_id
FROM test1
) AS src
SET emp_id = src.rn
WHERE test1.emp_id = src.emp_id -- must be unique column(s)
Btw, instead of updating all rows of a table it might be better to INSERT/SELECT or MERGE the SELECT into a new table. You must do it if there's no unique column, you should if emp_id is the PI of your table (otherwise performance will be horrible).
Create table test1(
emp_id decimal(5,0),
emp_name varchar(20),
emp_no INTEGER GENERATED ALWAYS AS IDENTITY
(START WITH 1
INCREMENT BY 1
)
);
Insert into test1(2015,'XYZ1',2);
Insert into test1(2016,'XYZ2',2);
Insert into test1(2015,'XYZ3',null);
Insert into test1(2016,'XYZ4',null);
I want to update status to inactive ( Status=āIā) for all duplicate record except one in sql, default status is active (Status=āAā ) for all records in table. It should be done without using any inbuilt sql function ex: row_num(), rank(), set rowcount etc.
CREATE TABLE dup_test
(
Emp_ID INT,
Mgr_ID INT,
Status Varchar(5)
)
INSERT INTO dup_test VALUES (1,1,'A');
INSERT INTO dup_test VALUES (1,1,'A');
INSERT INTO dup_test VALUES (1,1,'A');
INSERT INTO dup_test VALUES (2,2,'A');
INSERT INTO dup_test VALUES (2,2,'A');
INSERT INTO dup_test VALUES (3,3,'A');
Expected Result:
Emp_ID, Mgr_ID, Status
1 1 A
1 1 I
1 1 I
2 2 A
2 2 I
3 3 A
Thanks in advance.
Alter the table and add an identity column (ID):
ALTER TABLE dup_test
ADD id INT NOT NULL IDENTITY (1, 1)
Then something like the following will work:
UPDATE dup_test SET
Status='I'
FROM dup_test dt LEFT OUTER JOIN
(SELECT Emp_ID, MAX(ID) AS maxid
FROM dup_test
GROUP BY Emp_ID) AS dt2 ON dt.Emp_ID=dt2.Emp_ID AND dt.ID=dt2.maxid
WHERE dt2.maxID IS NULL
Can someone help explain this to me and resolve it?
http://sqlfiddle.com/#!6/2adc7/9
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_tblMobileForms_tblForms". The conflict occurred in database "db_6_2adc7", table "dbo.tblForms", column 'fm_id'.: insert into tblMobileForms(fm_name) values ('lol')
My schema has the ID from tblMobileForms be a foreign key to tblForms.fm_id
To do what you are trying to do you cannot set up the FK on tblMobileForms as an identity. See my fiddle below for more information.
http://sqlfiddle.com/#!6/be6f7/2
Alternatively what you could do is to have tblMobileForms have it's own separate surrogate key and have a different FK column to the tblForms table.
The PK on the tblMobileForms table has the same name as the FK on the same table. Seeing the PK is an IDENTITY column, you can end up with non-matching values.
In my fiddle, the tblForms table contained IDs in the upper 60s. Running the INSERT in the child table would add a record with id 1, which does not exist in the parent table.
I'd create a new row in the tblMobileForms table, and reference that to the parent table.
You could use an INSTEAD OF trigger to apply a random ID to each mobile form as it is inserted:
CREATE TRIGGER dbo.tblMobileForms_Insert
ON dbo.tblMobileForms
INSTEAD OF INSERT
AS
BEGIN
DECLARE #Inserted TABLE (fm_ID INT, fm_html_file VARBINARY(MAX), fm_name NVARCHAR(50));
INSERT #Inserted (fm_ID, fm_html_File, fm_Name)
SELECT fm_ID, fm_html_File, fm_Name
FROM inserted;
IF EXISTS (SELECT 1 FROM #Inserted WHERE fm_ID IS NULL)
BEGIN
WITH NewRows AS
( SELECT fm_ID, fm_html_File, fm_Name, RowNumber = ROW_NUMBER() OVER (ORDER BY fm_name)
FROM #Inserted
WHERE fm_ID IS NULL
), AvailableIDs AS
( SELECT fm_ID, RowNumber = ROW_NUMBER() OVER (ORDER BY fm_ID)
FROM tblForms f
WHERE NOT EXISTS
( SELECT 1
FROM tblMobileForms m
WHERE f.Fm_ID = m.fm_ID
)
AND NOT EXISTS
( SELECT 1
FROM inserted i
WHERE f.fm_ID = i.fm_ID
)
)
UPDATE NewRows
SET fm_ID = a.fm_ID
FROM NewRows n
INNER JOIN AvailableIDs a
ON a.RowNumber = n.RowNumber
IF EXISTS (SELECT 1 FROM #Inserted WHERE fm_ID IS NULL)
BEGIN
RAISERROR ('Not enough free Form IDs to allocate an ID to the inserted rows', 16, 1);
RETURN;
END
END
INSERT dbo.tblMobileForms (fm_ID, fm_html_File, fm_Name)
SELECT fm_ID, fm_html_file, fm_name
FROM #Inserted
END
When each row is inserted the trigger will check for the next available ID in tblForms and apply it sequentially to the inserted rows where fm_id is not specified. If there are no free ID's in tblForms then the trigger will throw an error so a 1 to 1 relationship is maintained (The error would be thrown anyway since tblMobileForms.fm_id is also a PK).
N.b. this requires tblForms.fm_ID to just be an int column, and not identity.