trigger at particular column with condition - sql

I want to check a Column value when update.If its match insert into another table.
My Tables:
My trigger:
CREATE TRIGGER tr_test
ON test1
FOR UPDATE
AS
SET nocount ON
IF ( Update(sname) )
DECLARE #Name NVARCHAR
DECLARE #id INT
SET #id=##IDENTITY
SET #Name=(SELECT sname
FROM test1
WHERE id = #id)
IF( #Name = 'Paras' )
BEGIN
INSERT INTO test2
(loginfo)
VALUES ('success')
END
And my update query is:
update Test1 set Sname='Paras' where ID=1
When I run this update query Nothing is happen.Test2 table is empty.I think problem is ##IDENTITY but not sure.Thanks.

Try this:
CREATE TRIGGER tr_test
ON test1
FOR UPDATE
AS
SET nocount ON
IF ( Update(sname) )
DECLARE #Name NVARCHAR
DECLARE #id INT
SET #id=(select id from inserted)
SET #Name=(SELECT sname
FROM inserted
WHERE id = #id)
IF( #Name = 'Paras' )
BEGIN
INSERT INTO test2
(loginfo)
VALUES ('success')
END
But it's better to do this, an update can update many rows, the above will fail if UPDATE matches many rows, use EXISTS:
CREATE TRIGGER tr_test
ON test1
FOR UPDATE
AS
SET nocount ON
IF( EXISTS(select * From inserted where sname = 'Paras' ) )
BEGIN
INSERT INTO test2
(loginfo)
VALUES ('success')
END
inserted table is the name of the table where the UPDATE's new values goes, deleted table is the name of the table where UPDATE's old values goes

Related

Updating two tables at once with values off the first one, and a variable

I'm trying to update with a passed variable in only the first row that has value NULL (multiple rows could have NULL in this column, but I need just the one),
Then I need to get the row affected (the primary key) and update the other table with it.
Here's what my two tables look like:
table1
id | some_value | ref_table2_id_fk
table2
id | name | ref_table1_id_fk
In my stored procedure I'm grabbing the passed value as #passed as int, then I try the following:
BEGIN
SET NOCOUNT ON;
DECLARE #id AS INT;
DECLARE #temp TABLE (id int);
BEGIN TRANSACTION;
BEGIN TRY
UPDATE TOP (1) [dbo].table1
SET ref_table2_id_fk = #passed
OUTPUT inserted.id INTO #temp
WHERE ref_table2_id_fk = NULL
UPDATE [dbo].table2
SET ref_table1_id_fk = #temp.id
FROM table2
JOIN #temp i on i.id = table2.id;
SET #id = ##IDENTITY
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0
BEGIN
--some error
ROLLBACK TRANSACTION;
RETURN 0;
END
END CATCH;
IF ##TRANCOUNT > 0
BEGIN
--success
COMMIT TRANSACTION;
RETURN #Id;
END
END
As pointed out by Dale ##identity doesn't work in update. My intention is to simply know if the transaction went through or not.
I think the following code does what you are asking. Things fixed:
where ref_table2_id_fk = null should be where ref_table2_id_fk is null
You can't use TOP in an update statement you need a sub-query to get the id.
You're not providing an id in #temp to join onto table2 - you need the table1 id and the table2 id for a joined update.
If I understand your logic the id you want to return is #passed - you already have it.
#temp.id should be i.id since you've (rightly) aliased it
declare #Passed int = 3;
declare #table1 table (id int, some_value varchar(12), ref_table2_id_fk int);
declare #table2 table (id int, some_value varchar(12), ref_table1_id_fk int);
insert into #table1 (id)
select 1 union all select 2;
insert into #table2 (id)
select 3 union all select 4;
select * from #table1;
select * from #table2;
DECLARE #id AS INT, #Result bit = 0;
DECLARE #temp TABLE (id int, fk int);
BEGIN TRANSACTION;
BEGIN TRY
UPDATE #table1
SET ref_table2_id_fk = #passed
OUTPUT #passed, inserted.id INTO #temp
WHERE id = (
select top 1 id
from #table1
where ref_table2_id_fk is NULL
-- Optionally order by if you have a priority here
);
UPDATE T2
SET ref_table1_id_fk = i.fk
FROM #table2 T2
JOIN #temp i on i.id = T2.id
where T2.id = #passed;
-- If we get here then everything worked
-- Return #Result at the end of the proc
SET #Result = 1;
END TRY
begin catch
no_op:;
end catch
select * from #table1;
select * from #table2;

Return one OUTPUT result from MERGE query

I have a merge query which updates or inserts if no records found. In my results, I have a problem when the record does not exist and it get inserted. The query returns BOTH 'Updated' (as empty) and 'Inserted' (with the proper value).
Any ideas how to avoid return the empty 'Updated' when there are no updates?
ALTER PROCEDURE [dbo].[spInsOrUpdApplicant]
-- Add the parameters for the stored procedure here
#Name nvarchar(50),
#Surname nvarchar(50),
#Position nvarchar(50),
#NationalID int,
#ApplicantID int
AS
BEGIN
SET NOCOUNT ON;
-- Update the row if it exists.
UPDATE tbApplicant
SET Name = #Name, Surname = #Surname, Position = #Position, NationalID = #NationalID
OUTPUT INSERTED.ApplicantID AS 'Result'
WHERE ApplicantID = #ApplicantID;
-- Insert the row if the UPDATE statement failed.
IF (##ROWCOUNT = 0 )
BEGIN
INSERT INTO tbApplicant (Name, Surname, Position, NationalID)
OUTPUT INSERTED.ApplicantID AS 'Result'
VALUES (#Name, #Surname, #Position, #NationalID)
END
END;
It seems that the 'output' always fires even if no actual rows were updated. You can see the same behavior in triggers. You might want to consider doing the following:
ALTER PROCEDURE [dbo].[spInsOrUpdApplicant]
-- Add the parameters for the stored procedure here
#Name nvarchar(50),
#Surname nvarchar(50),
#Position nvarchar(50),
#NationalID int,
#ApplicantID int
AS
BEGIN
SET NOCOUNT ON;
-- Check if the row exists.
IF EXISTS (SELECT 1 FROM tbApplicant WHERE ApplicantID = #ApplicantID) BEGIN
-- update if the row exists.
UPDATE tbApplicant
SET Name = #Name, Surname = #Surname, Position = #Position, NationalID = #NationalID
OUTPUT INSERTED.ApplicantID AS 'Result'
WHERE ApplicantID = #ApplicantID;
END
ELSE BEGIN
-- Else Insert.
INSERT INTO tbApplicant (Name, Surname, Position, NationalID)
OUTPUT INSERTED.ApplicantID AS 'Result'
VALUES (#Name, #Surname, #Position, #NationalID)
END
END;
I do something very similar.
Inside my stored procedure, I have this:
DECLARE #mergeResults TABLE (mergeAction varchar(10), tableName varchar(50));
OUTPUT $action, 'Table Name' INTO #mergeResults;
Can you insert into the table variable and then decide how you want to move the data based on what you see?
You mentioned you have a merge query but you aren't using a merge - you're using more of an "upsert".
Merge T-SQL: http://msdn.microsoft.com/en-us/library/bb510625.aspx

update trigger get the updated primary key

I have a trigger ,but I need to get the updated record's primary key (like as inserting the data SELECT #Id= ##IDENTITY) thus, I can pass it to where condition. How can I do that?
ALTER TRIGGER [dbo].[CariBakiyeBorcAktar]
ON [dbo].[BakimKartiDegisenParcalar]
AFTER UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #Id int
DECLARE #CariId int
DECLARE #SId int
DECLARE #MId int
declare #Tutar decimal
declare #Bakiye decimal
declare #s decimal = 0
DECLARE #ParcaId int
--how I can I get the last updateed record Identity like this??
--and pass it to update query as a where condition
SELECT #Id= ##IDENTITY
set #SId=(select SId from CariBakiye where Id =#Id)
select #CariId=tblk.CariId ,#MId=tblk.MId, #SId= tblk.SId,#Tutar=tblk.Tutar from (
SELECT tbl.CariId , tbl.MId,tbl.SId,tbl.Tutar from (select cb.MId,SUM(bk.Tutar) as Tutar,bk.SId,cb.Id as CariId FROM [BakimKartiDegisenParcalar] bk
join CariBakiye cb on cb.SId=bk.SId
where bk.SId =cb.SId group by bk.SId,cb.MId,cb.Id ) as tbl
) as tblk where SId = #SId
set #Bakiye = #s-#Tutar
update CariBakiye set Borc=#Tutar,Bakiye=#Bakiye where Id=#CariId
print #Id
-- Insert statements for trigger here
END
As Martin said, you have to understand that SQL Server triggers are per statement, not per row. So in context of your trigger you have two tables - inserted and deleted, where you could find all information about data updated. If you really want to do per row processing, you could use cursor:
ALTER TRIGGER [dbo].[CariBakiyeBorcAktar] ON [dbo].[BakimKartiDegisenParcalar]
AFTER UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #Id int
DECLARE #CariId int
DECLARE #SId int
DECLARE #MId int
declare #Tutar decimal
declare #Bakiye decimal
declare #s decimal = 0
DECLARE #ParcaId int
declare tr_cursor cursor local fast_forward for
select ID from inserted
while 1 = 1
begin
fetch tr_cursor into #Id
if ##fetch_status <> 0 break
set #SId=(select SId from CariBakiye where Id =#Id)
select #CariId=tblk.CariId ,#MId=tblk.MId, #SId= tblk.SId,#Tutar=tblk.Tutar from (
SELECT tbl.CariId , tbl.MId,tbl.SId,tbl.Tutar from (select cb.MId,SUM(bk.Tutar) as Tutar,bk.SId,cb.Id as CariId FROM [BakimKartiDegisenParcalar] bk
join CariBakiye cb on cb.SId=bk.SId
where bk.SId =cb.SId group by bk.SId,cb.MId,cb.Id ) as tbl
) as tblk where SId = #SId
set #Bakiye = #s-#Tutar
update CariBakiye set Borc=#Tutar,Bakiye=#Bakiye where Id=#CariId
print #Id
-- Insert statements for trigger here
end
close tr_cursor
deallocate tr_cursor
END

Condition in a stored procedure

i have a stored procedure that does 2 updates, but i only want to do the first update if the parameter #active is equals to 'Y'.
alter procedure sp_updateThis
#something varchar(5),
#active char(1)
as begin
-- check to see if active and do the update
update myTable set this=#something
-- run this one regardless
update yourTable set that=#something
Try changing that last line with this:
if (#active = 'Y')
begin
update yourTable set that=#something
end
alter procedure sp_updateThis
#something varchar(5),
#active char(1)
as begin
-- check to see if active and do the update
if(#active = 'Y')
Begin
update myTable set this=#something
End
-- run this one regardless
update yourTable set that=#something
If you're really trying to update every row in the table:
update myTable set this=#something where #active = 'Y';
Otherwise you probably want additional clauses there...
you can create a procedure like this:
create procedure sp_updateThis
#something varchar(5),
#active char(1)
AS
Begin
if #active ='y'
begin
update yourTable set that=#something
end
else
update myTable set this=#something
update yourTable set that=#something
end
go

SQL Update trigger doesn't work as expected

I have a problem with the programming of an Update trigger. I want to create a trigger that copies the row I edited in a new row with the new data and a new ID. The old row should be the same with just a flag change from 0 to 1.
The table look like this:
ID Artikelname PREIS UPDATE_DATE FLAG
1 Tomatoe 3 14.06.2012 16:00 0
2 Apple 1,5 12.05.2012 14:45 0
When I change the price of the first row, the table should look like this:
ID Artikelname PREIS UPDATE_DATE FLAG
1 Tomatoe 3 14.06.2012 16:00 1
2 Apple 1,5 12.05.2012 14:45 0
1 Tomatoe 2 13.07.2012 10:45 0
Here is my trigger so far:
USE [TestDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[Produkt_Update]
ON [dbo].[Produkt]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON
DECLARE #ID int
DECLARE #Artikelname nvarchar(50)
DECLARE #Preis numeric
DECLARE #Flag numeric
DECLARE #max_id int
SET #ID = (SELECT ID FROM inserted)
SET #Artikelname = (SELECT Artikelname FROM inserted)
SET #Preis = (SELECT Preis FROM inserted)
SET #Flag = (SELECT Flag FROM inserted)
SET #max_id = (SELECT MAX(ID) from dbo.Produkt)
SET IDENTITY_INSERT dbo.Produkt ON
INSERT INTO dbo.Produkt
(ID,Artikelname,Preis)
values (#max_id+1,#Artikelname,#Preis)
SET IDENTITY_INSERT dbo.Produkt OFF
UPDATE dbo.Produkt
SET Flag = 1
WHERE ID=#ID
END
With my trigger I can create the new row but the price on the first row sill changes. I don't know how to handle this. Could you help me please?
Please try this and let me know
CREATE TRIGGER [dbo].[Produkt_Update]
ON [dbo].[Produkt]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE #MAX_ID INT;
SELECT #MAX_ID=MAX(ID) FROM [Produkt];
declare #tmp Table(ID int, Artikelname varchar(200),
PREIS varchar(200),UPDATE_DATE datetime, FLAG bit)
insert into #tmp
select ID,Artikelname,PREIS,UPDATE_DATE,1 [flag] from deleted;
delete T from [Produkt] T JOIN #tmp I
ON T.ID=I.ID
SET IDENTITY_INSERT [Produkt] ON
INSERT INTO [Produkt] (ID,Artikelname,PREIS,UPDATE_DATE,FLAG)
SELECT #MAX_ID+ROW_NUMBER() OVER(ORDER BY ID) [ID],Artikelname,PREIS,GETDATE(),0
FROM INSERTED
union all
select * from #tmp
SET IDENTITY_INSERT dbo.Produkt OFF
SET NOCOUNT OFF;
END;
You need to insert the price (preis) from the deleted table, not the inserted table
Replace
SET #ID = (SELECT ID FROM inserted)
with
SET #ID = (SELECT ID FROM deleted)