Trigger being called on all rows in database - sql

I have written a trigger that I want to use for adding the date to a column in a record so that I can keep track of the insert of the item.
There are a large amount of inserts being called (about 20000) and I have noticed that the trigger will update all of the InsertDate columns associated with each item every time a new item is added. How can I make sure this happens to an item being inserted only one time.
My trigger is as follows:
SET ANSI_NULLS ON
SET QUOTED_INDENTIFIER ON
GO
CREATE TRIGGER [InsertDate_Item]
ON [dbo].[ItemHolder]
AFTER INSERT
NOT FOR REPLICATION
AS
UPDATE ItemHolder SET InsertDate = GETDATE()
Any help will be much appreciated.
Thanks

You need to restrict rows to those inserted... using the virtual trigger table INSERTED
CREATE TRIGGER [InsertDate_Item]
ON [dbo].[ItemHolder]
AFTER INSERT
NOT FOR REPLICATION
AS
SET NOCOUNT ON
UPDATE IH
SET InsertDate = GETDATE()
FROM
ItemHolder IH
JOIN
INSERTED INS ON IH.keycol = INS.keycol
Go
One thing: You'd be better adding a default to the table instead. No need for a trigger
ALTER TABLE ItemHolder ADD
CONSTRAINT DF_ItemHolder_InsertDate DEFAULT (GETDATE()) FOR InsertDate

If you are inserting records into a table, why don't you make the InsertDate field have a default value of GetDate()? That avoids the trigger altogether.

I'd go about what you're trying to do without a trigger. Just set the default value of the column to GetDate().

update ih
set ih.insertdate = GetDate()
from itemholder ih inner join inserted i
on ih.itemholderid = i.itemholderid

change:
UPDATE ItemHolder SET InsertDate = GETDATE()
to:
UPDATE ItemHolder SET InsertDate = GETDATE() WHERE InsertDate IS NULL
The above will only set InsertDate if it is null and you still want to use the trigger. Of course, this is assuming the default value of InsertDate is null. If this is not the case let me know.

Related

Create a Table that has Created Date and Update Date (Read Only)

I wonder if it is possible to create a table that has a created date and updated date every time a record is created or updated.
For example, when I insert a record into that table, the created date will auto generated in the table same with the update date.
When I modify this record, the create date won't change but the update date will change according to the date.
Many thanks
CREATE TABLE dbo.foo
(
ID INT IDENTITY(1,1),
CreatedDate DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
UpdatedDate DATETIME NULL
);
GO
CREATE TRIGGER dbo.foo_ForUpdate
ON dbo.foo
FOR UPDATE
AS
BEGIN
SET NOCOUNT ON;
UPDATE f SET UpdatedDate = CURRENT_TIMESTAMP
FROM dbo.foo AS f
INNER JOIN inserted AS i
ON f.ID = i.ID;
END
GO
You can set the default value for the column to be equal to GetDate() and this will set the Created Date to the time when the record was created. This will not work for UpdatedDate because default values will be used when the record is created. For this column you can use after update trigger. Here is a link that shows how to create one :
http://www.sqlservercurry.com/2010/09/after-update-trigger-in-sql-server.html
Trigger is a most suitable option. You can refer the sample for trigger as follows.
CREATE TRIGGER dbo.TableTriggerName
ON dbo.TableName
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
SET NOCOUNT ON;
--
-- Check if this is an INSERT, UPDATE or DELETE Action.
-- Set Action to Insert by default.
IF EXISTS(SELECT * FROM DELETED)
BEGIN
END
ELSE
IF NOT EXISTS(SELECT * FROM INSERTED) RETURN; -- Nothing updated or inserted.
...
END
Trigger Reference

update field by using Triggers in MS SQL

i have simple question regarding Triggers in sql.
I am completely new and i do not know how to handle it.
I have one table myshift with shiftid, starttime stoptime and lastupdate.
create trigger ShiftTriggerr on myshift for update as
if update(stoptime)
update myshift set lastupdated = getdate()
what i want is when stoptime will update, the lastupdate field will update with getdate().
but when i run this it does not update one row but updated all rows. I do not know how to apply check on this trigger
You need to use the INSERTED virtual table:
CREATE TRIGGER dbo.ShiftTriggerr
ON dbo.myshift AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF UPDATE(stoptime)
BEGIN
UPDATE A
SET lastupdated = getdate()
FROM dbo.myshift A
INNER JOIN INSERTED B
ON A.shiftid = B.shiftid
END
END
myshift should have a primary key defined, if that is shiftId, then,
create trigger ShiftTriggerr on myshift for update as
update m
set lastupdated = getdate()
From myshift m Join inserted i
on i.shiftId = m.shiftId

Data Type that automatically stores the DateTime of the last transaction done, SQL Server 2008

I need to add a new column to an existing table, so that whenever a new row is added, or an existing row is edited, this column will be filled with the exact date and time of the transaction. I tried using TimeStamp but apparently TimeStamp it has nothing to do with Date time
It's just a binary representation of a consecutive number - it's only good for making sure a row hasn't change since it's been read. (Quoted from How to convert SQL Server's timestamp column to datetime format
Any help is highly appreciated
It sounds like you need to create a trigger to populate/update this new column. See the following: How to: Create trigger for auto update modified date with SQL Server 2008
You have to create a trigger on INSERT and UPDATE for the table and in the trigger you can use
UPDATE myTable
SET myColumn = GETDATE()
Your trigger should look somethign like
CREATE TRIGGER trigger_updateTimestamp
ON myTable
AFTER INSERT, UPDATE
AS
UPDATE myTable
SET myColumn = GETDATE()
WHERE ID = 'xyz'
try
ALTER TABLE myTable ADD CONSTRAINT [DF_myTable_myColumn] DEFAULT (getdate()) FOR [myColumn]
GO
... and a good practice is to have an extra column for edited date, and update using a trigger
CREATE TRIGGER trigger_updateMyTable
ON myTable
AFTER UPDATE
AS
IF EXISTS (SELECT * FROM INSERTED)
BEGIN
IF ΝΟΤ EXISTS (SELECT * FROM DELETED)
BEGIN
UPDATE myTable
SET myEditColumn = GETDATE()
WHERE ID IN (
SELECT
ID
FROM INSERTED
)
END
END

sql - Update Trigger to populate a ModifyDate field

I'm looking for an example of a good update trigger to update the ModifyDate field of a table.
It would be nice to handle the case where an update command updated more than one record in the table.
Is there a good template or tutorial for this?
Here's a cut and paste (and rename, to protect the innocent) of one I wrote quite some time ago (aka it works):
CREATE TRIGGER dbo.TR_iu_MyTable__LastUpdated
on dbo.MyTable
after insert, update
AS
SET NOCOUNT on
UPDATE dbo.MyTable
set LastUpdated = getdate()
where MyTableId in (select MyTableId from inserted)
UPDATE {tablename}
SET ModifyDate = GETDATE()
FROM inserted
WHERE {tablename}.{primarykey} = inserted.{primarykey}
Placed in a trigger tagged for INSERT and UPDATE actions will address your problem.
You could also do something similar for a CreateDate
UPDATE {tablename}
SET CreateDate = GETDATE()
FROM inserted
WHERE {tablename}.{primarykey} = inserted.{primarykey}
placed in a trigger tagged for INSERT action only.

DateCreated column in Sql Server?

Is there a special way to declare a DateCreated column in a MS Sql Server table so that it will automatically fill it with the appropriate time-stamp when created?
Or.. do I have to provide the datetime to it when I do the query, manually?
Default values suffer from two major drawbacks.
if the insert statement specifies a value for the column, the default isn't used.
the column can be updated any time.
These mean that you can't be certain that the values haven't been modified outside of your control.
If you want true data integrity (so that you're sure the date in the row is the creation date), you need to use triggers.
An insert trigger to set the column to the current date and an update trigger to prevent changes to that column (or, more precisely, set it to its current value) are the way to implement a DateCreated column.
An insert and update trigger to set the column to the current date is the way to implement a DateModified column.
(edit from user Gabriel - here's my attempt to implement this as described - i'm not 100% sure it's correct but I'm hoping the OP reviews it...):
CREATE TRIGGER [dbo].[tr_Affiliate_IU]
ON [dbo].[Affiliate]
AFTER INSERT, UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Get the current date.
DECLARE #getDate DATETIME = GETDATE()
-- Set the initial values of date_created and date_modified.
UPDATE
dbo.Affiliate
SET
date_created = #getDate
FROM
dbo.Affiliate A
INNER JOIN INSERTED I ON A.id = I.id
LEFT OUTER JOIN DELETED D ON I.id = D.id
WHERE
D.id IS NULL
-- Ensure the value of date_created does never changes.
-- Update the value of date_modified to the current date.
UPDATE
dbo.Affiliate
SET
date_created = D.date_created
,date_modified = #getDate
FROM
dbo.Affiliate A
INNER JOIN INSERTED I ON A.id = I.id
INNER JOIN DELETED D ON I.id = D.id
END
You can set the default value of the column to "getdate()"
We have DEFAULT on CreatedDate and don't enforce with Triggers
There are times when we want to set the date explicitly - e.g. if we import data from some other source.
There is a risk that Application Bug could mess with the CreateDate, or a disgruntled DBA for that matter (we don't have non-DBAs connecting direct to our DBs)
I suppose you might set Column-level permissions on CreateDate.
A half-way-house might be to have an INSERT TRIGGER create a row in a 1:1 table, so that column was outside the main table. The second table could have SELECT permissions, where the main table has UPDATE permissions, and thus not need an UPDATE trigger to prevent changes to CreateDate - which would remove some "weight" when updating rows normally.
I suppose you coul have an UPDATE/DELETE trigger on the second table to prevent change (which would never be executed in normal circumstances, so "lightweight")
Bit of a pain to have the extra table though ... could have one table for all CreateDates - TableName, PK, CreateDate. Most database architects will hate that though ...
Certainly is.
Here is an example in action for you.
Create table #TableName
(
ID INT IDENTITY(1,1) PRIMARY KEY,
CreatedDate DATETIME NOT NULL DEFAULT GETDATE(),
SomeDate VARCHAR(100)
)
INSERT INTO #TableName (SomeDate)
SELECT 'Some data one' UNION ALL SELECT 'some data two'
SELECT * FROM #TableName
DROP TABLE #TableName
Setting the default value isn't enough, you should add a trigger to prevent updating:
CREATE TRIGGER UpdateRecord ON my_table
AFTER UPDATE AS UPDATE my_table
SET [CreatedDate] = ((SELECT TOP 1 [CreatedDate] FROM Deleted d where d.[id]=[id]))