Is it possible to create and execute 2 triggers on one table - sql

I am trying to find some workaround to create and execute multiple triggers for different tables on one table. I have 2 tables
Person Detail
Address
The way this table is designed is when a user updates Person's address it creates a new record into address table instead of updating the existing one and I want to insert the changes into auditlog table when a user updates person details or address.
I was able to create a trigger for person table but dont know how can i make it work by using or calling multiple triggers on Person Table
Following is the code for Person table update trigger
CREATE TRIGGER [dbo].[tr_tblPersonDetail_ForUpdate]
ON [dbo].[PersonDetail]
FOR Update
AS
BEGIN
Declare #Id int,
Declare #OldFirstName varchar(50), #NewFirstName varchar(50)
BEGIN
Select #Id=personId,#NewFirstName = NewFirstName from Inserted
select #OldFirstName = NewFirstName from deleted where #id = personId
if(#OldFirstName <> #NewFirstName )
Insert into AuditLog values('some value','AfterValue','Before Value')

Yes, one table may have multiple triggers. You do need to exercise caution, however - you may not want every update to fire both triggers, or you may have need to execute the triggers in a particular order.
It really sounds like you want an INSTEAD OF UPDATE trigger for the requirement of
creates a new record into address table instead of updating the existing one
If you need your trigger to execute only if specific field(s) were updated, use UPDATED() to test for them.
You can use sp_settriggerorder to dictate which trigger should execute and which one last.
In your case, I would suggest an AFTER UPDATE for any operation that changes only the person's name, and then an INSTEAD OF UPDATE which handles cases where the address is changed (which will also need to handle the name change).
If you choose to continue down the path of using triggers at all.

Related

Automatically fill row with value based on inserted id

I have a table where the user is able to insert the ID of a Node that corresponds to a title elsewhere in the database. I want this tile to be automatically inserted into the row after the user has chosen the id.
This is my table:
I need to have the "SommerhusNavn" column be automatically filled with values based on the "SommerhusId" inserted.
I am using a third party to handle the CRUD functionality, where the user picks the ID from a dropdown. I already know in which table the title for the ID is located, I'm just not sure how to fill the row with the insert statement. Would I need to run a separate query for this to happen?
Edit:Solution
CREATE TRIGGER [dbo].[BlokeredePerioderInsert]
ON dbo.BlokeredePerioder
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
UPDATE BlokeredePerioder SET SommerhusNavn = text FROM umbracoNode AS umbNode
where SommerhusId = umbNode.id
END
GO
Yes, you need to run additional UPDATE query. Let's assume that you have the TitlesTable, with columns ID and Title. Then it should look like:
UPDATE MyTable SET SommerhusNavn = Title FROM TitlesTable AS A
WHERE SommerhusId = A.ID
AND SommerhusNavn IS NOT NULL --not necessary
Perhaps i'm not understanding, but why can't you use send the value across in the initial update?
Can you use a trigger on the database side?
Alternatively, you'll need to send a update across, following the insert.

How to insert into the table a user name record

I've a table. In this table I have two columns - 'insert_name' and 'modified_name'. I need to insert into this columns data about who has inserted data into the table('insert_name') and who has changed these data in the table (modified_name). How it can be done?
You are looking for basic DML statements.
If your record is already in the table, then you need to UPDATE it. Otherwise, when you are about to add your record to it and it doesn't already exist in the destination table then you are looking for INSERT INTO statement.
Example of updating information for record with first id:
UPDATE yourtable SET insert_name = 'value1', modified_name = 'value2' WHERE id = 1
Example of inserting new record:
INSERT INTO yourtable(id, company_name, product_name, insert_name)
VALUES (1, 'Google', 'PC', 'value1')
If you are looking for automatic changes to those columns then you need to look into triggers.
Remember that more often than not you may find that the application connecting to the database is using single database user in which case you probably know the context within the application itself (who inserts, who updates). This does eliminate triggers and put the task straight on simple insert/update commands from within your application layer.
You might be able to use the CURRENT_USER function to find the name of the user making the change.
The value from this function could then be used to update the appropriate column. This update could be done as part of the INSERT or UPDATE statement. Alternatively use an INSERT or UPDATE trigger.
Personally I avoid triggers if I can.
For those 2 columns add Current_User as Default constraint.
As the first time Insert Statement will save them with current login user names. For update write an Update trigger with the same Current_User statement for the column Modified_Name.
If and only if your application business logic can't update the column modified_nme then only go for Trigger.
See the use of Current_Use
https://msdn.microsoft.com/en-us/library/ms176050.aspx

SQL Server : How to track changes value in a column and send notification email for only changed values

I have a table as below that contains dealer codes and status. Every night between 1 and 6am the status column may change for each dealer code. For example today the status of 00141.00062 is operational, but tomorrow it will be deactivated if the store was closed.
Briefly,I would like to track the changes using by stored procedures and send a notification email to me just for the updated values.
Lastly, I do not prefer to create a trigger cause of according to my previous experience it will be affect my main app. Therefore, I will be aprreciate if you can explain how I can do it via stored procedures.
DEALER_CODE STATUS
----------------------------
00141.00062 OPERASYONEL
01033.00061 DEACTIVE
00070.00002 DEACTIVE
00524.00002 DEACTIVE
00387.00020 DEACTIVE
00543.00001 DEACTIVE
00310.00061 DEACTIVE
00247.00062 OPERATIONAL
If your UPDATE statement affects multiple rows at once, you'll get the trigger fired once, but with multiple rows in the Deleted (old values before UPDATE) and Inserted (new values after UPDATE) pseudo tables. Therefore, it's the easiest to just compare those pseudo tables to figure out which rows have changed.
Also: I would strongly recommend to NOT send the e-mail directly from the trigger, since the trigger executes in the context of the UPDATE statement that caused it to fire and thus any delay in sending the e-mail just slows down your main app.
Instead, just add a row into a table, and then periodically (once every night, once every 4 hours or whatever suits your needs) have a separate process grab the new rows from that table and put those into an e-mail.
So the trigger should look something like this:
CREATE TRIGGER trgUpdateStatus
ON dbo.YourTableName
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
-- insert a row into a "changed" table that will then be
-- used to asynchronously send out e-mails
INSERT INTO dbo.ChangedDealerStatuses (DealerCode, OldStatus, NewStatus)
SELECT
old.Dealer_Code, old.Status, new.Status
FROM
Deleted old
INNER JOIN
Inserted new ON old.Dealer_Code = new.Dealer_Code
WHERE
old.Status <> new.Status
END
You can use an after update trigger for this purpose. This is sample code:
CREATE TRIGGER TRIGGERNAME -- NAME OF TRIGGER
ON TABLENAME -- NAME OF YOUR TABLE
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF UPDATE([STATUS])
BEGIN
PRINT 'STATUS COLUMN IS UPDATED'
---------------------TODO------------
-- INSERT INTO TABLE OR SEND EMAIL-------
END
END
Note: please note that if update statement will be executed if update operation on column status. It never check if you have updated with same value.

How to check if a column is being updated in an INSTEAD OF UPDATE Trigger

I am making some tweaks to a legacy application built on SQL Server 2000, needless to say I only want to do the absolute minimum in the fear that it may just all fall apart.
I have a large table of users, tbUsers, with a BIT flag for IsDeleted. I want to archive off all current and future IsDeleted = 1 user records into my archive table tbDeletedUsers.
Moving the currently deleted users is straight forward, however I want a way to move any future users where the IsDeleted flag is set. I could use a standard AFTER trigger on the column however I plan to add some constraints to the tbUser table that would violate this, what I'd like is for my INSTEAD OF UPDATE trigger to fire and move the record to archive table instead?
I guess my question is... is it possible to trigger an INSTEAD OF UPDATE trigger on the update of an individual column? This is what I have so far:
CREATE TRIGGER trg_ArchiveUsers
INSTEAD OF UPDATE ON tbUsers
AS
BEGIN
...
END
GO
If so an example (SQL 2000 compatible) would be much appreciated!
Using the UPDATE(columnname) test, you can check in a trigger whether a specific column was updated (and then take specific actions), but you can't have a trigger fire only on the update of a specific column. It will fire as soon as the update is performed, regardless of the fact which column was the target of the update.
So, if you think you have to use an INSTEAD OF UPDATE trigger, you'll need to implement two kinds of actions in it:
1) insert into tbDeletedUsers + delete from tbUsers – when IsDeleted is updated (or, more exactly, updated and set to 1);
2) update tbUsers normally – when IsDeleted is not updated (or updated but not set to 1).
Because more than one row can be updated with a single UPDATE instruction, you might also need to take into account that some rows might have IsDeleted set to 1 and others not.
I'm not a big fan of INSTEAD OF triggers, but if I really had to use one for a task like yours, I might omit the UPDATE() test and implement the trigger like this:
CREATE TRIGGER trg_ArchiveUsers
ON tbUsers
INSTEAD OF UPDATE
AS
BEGIN
UPDATE tbUsers
SET
column = INSERTED.column,
…
FROM INSERTED
WHERE INSERTED.key = tbUsers.key
AND INSERTED.IsDeleted = 0
;
DELETE FROM tbUsers
FROM INSERTED
WHERE INSERTED.key = tbUsers.key
AND INSERTED.IsDeleted = 1
;
INSERT INTO tbDeletedUsers (columns)
SELECT columns
FROM INSERTED
WHERE IsDeleted = 1
;
END

Need some help with Sql Server and a simple Trigger

I wish to make a trigger but i'm not sure how to grab the data for whatever caused the trigger.
I have a simlpe table.
FooId INT PK NOT NULL IDENTITY
Name VARCHAR(100) NOT NULL
I wish to have a trigger so that when an UPDATE, INSERT or DELETE occurs, i then do the following.
Pseduocode
IF INSERT
Print 'Insert' & Name
ELSE IF UPDATE
Print 'Update' & FooId & Name
ELSE IF DELETE
Print 'Delete' & FooId & Name
Now, I know how to make a trigger for a table.
What i don't know how to do is figure out the values based on what the trigger type is.
Can anyone help?
Edit: Not sure if it helps, but db is Sql Server 2008
the pseudo table "inserted" contains the new data, and "deleted" table contains the old data.
You can do something like
create trigger mytrigger on mytable for insert, update, delete
as
if ( select count(*) from inserted ) > 0
-- insert or update
select FooId, Name from inserted
else
-- delete
select FooId, Name from deleted
To clarify all the comments made by others, on an insert, the inserted table contains data and deleted is empty. On a delete, the situation is reversed. On an update, deleted and inserted contain the "before" and "after" copy of any updated rows.
When you are writing a trigger, you have to account for the fact that your trigger may be called by a statement that effects more than one row at a time.
As others have pointed out, you reference the inserted table to get the values of new values of updated or inserted rows, and you reference the deleted table to get the value of deleted rows.
SQL triggers provide an implicitly-defined table called "inserted" which returns the affected rows, allowing you to do things like
UPDATE mytable SET mytimestamp = GETDATE() WHERE id IN (SELECT id FROM inserted)
Regarding your code sample, you'll want to create separate INSERT, UPDATE and DELETE triggers if you are performing separate actions for each.
(At least, this is the case in SQL Server... you didn't specify a platform.)
On 2008, there is also MERGE command. How do you want to handle it?
Starting from 2008, there are four commands you can modify a table with:
INSERT, UPDATE, DELETE, and MERGE:
http://blogs.conchango.com/davidportas/archive/2007/11/14/SQL-Server-2008-MERGE.aspx
http://sqlblogcasts.com/blogs/grumpyolddba/archive/2009/03/11/reasons-to-move-to-sql-2008-merge.aspx
What do you want your trigger to do when someone issues a MERGE command against your table?