SQL trigger to insert values when the tables updated - sql-server

I have written a trigger to execute when data is inserted on to a SQL Server table via a SSIS package. I want to insert today's date in to the date column in the table. My trigger is below it doesn't seem to work.
Can some one please help.
ALTER TRIGGER [dbo].[InsertDate]
ON dbo.Debtors
AFTER INSERT
AS
BEGIN
UPDATE dbo.Debtors
SET InsertDate = GETDATE()
FROM inserted
WHERE Debtors.id = inserted.id
END

Use a default value instead:
alter table dbo.Debtors add column InsertDate datetime default getdate();
No need for a trigger at all.

Related

Can I determine when a Azure SQL DB row was last updated? [duplicate]

I need to create a new DATETIME column in SQL Server that will always contain the date of when the record was created, and then it needs to automatically update whenever the record is modified. I've heard people say I need a trigger, which is fine, but I don't know how to write it. Could somebody help with the syntax for a trigger to accomplish this?
In MySQL terms, it should do exactly the same as this MySQL statement:
ADD `modstamp` timestamp NULL
DEFAULT CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP
Here are a few requirements:
I can't alter my UPDATE statements to set the field when the row is modified, because I don't control the application logic that writes to the records.
Ideally, I would not need to know the names of any other columns in the table (such as the primary key)
It should be short and efficient, because it will happen very often.
SQL Server doesn't have a way to define a default value for UPDATE.
So you need to add a column with default value for inserting:
ADD modstamp DATETIME2 NULL DEFAULT GETDATE()
And add a trigger on that table:
CREATE TRIGGER tgr_modstamp
ON **TABLENAME**
AFTER UPDATE AS
UPDATE **TABLENAME**
SET ModStamp = GETDATE()
WHERE **ID** IN (SELECT DISTINCT **ID** FROM Inserted)
And yes, you need to specify a identity column for each trigger.
CAUTION: take care when inserting columns on tables where you don't know the code of the application. If your app have INSERT VALUES command without column definition, it will raise errors even with default value on new columns.
This is possible since SQL Server 2016 by using PERIOD FOR SYSTEM_TIME.
This is something that was introduced for temporal tables but you don't have to use temporal tables to use this.
An example is below
CREATE TABLE dbo.YourTable
(
FooId INT PRIMARY KEY CLUSTERED,
FooName VARCHAR(50) NOT NULL,
modstamp DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL,
MaxDateTime2 DATETIME2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL,
PERIOD FOR SYSTEM_TIME (modstamp,MaxDateTime2)
)
INSERT INTO dbo.YourTable (FooId, FooName)
VALUES (1,'abc');
SELECT *
FROM dbo.YourTable;
WAITFOR DELAY '00:00:05'
UPDATE dbo.YourTable
SET FooName = 'xyz'
WHERE FooId = 1;
SELECT *
FROM dbo.YourTable;
DROP TABLE dbo.YourTable;
It has some limitations.
The time stored will be updated by the system and always be UTC.
There is a need to declare a second column (MaxDateTime2 above) that is completely superfluous for this use case. But it can be marked as hidden making it easier to ignore.
Okay, I always like to keep track of not only when something happened but who did it!
Lets create a test table in [tempdb] named [dwarfs]. At a prior job, a financial institution, we keep track of inserted (create) date and updated (modify) date.
-- just playing
use tempdb;
go
-- drop table
if object_id('dwarfs') > 0
drop table dwarfs
go
-- create table
create table dwarfs
(
asigned_id int identity(1,1),
full_name varchar(16),
ins_date datetime,
ins_name sysname,
upd_date datetime,
upd_name sysname,
);
go
-- insert/update dates
alter table dwarfs
add constraint [df_ins_date] default (getdate()) for ins_date;
alter table dwarfs
add constraint [df_upd_date] default (getdate()) for upd_date;
-- insert/update names
alter table dwarfs
add constraint [df_ins_name] default (coalesce(suser_sname(),'?')) for ins_name;
alter table dwarfs
add constraint [df_upd_name] default (coalesce(suser_sname(),'?')) for upd_name;
go
For updates, but the inserted and deleted tables exist. I choose to join on the inserted for the update.
-- create the update trigger
create trigger trg_changed_info on dbo.dwarfs
for update
as
begin
-- nothing to do?
if (##rowcount = 0)
return;
update d
set
upd_date = getdate(),
upd_name = (coalesce(suser_sname(),'?'))
from
dwarfs d join inserted i
on
d.asigned_id = i.asigned_id;
end
go
Last but not least, lets test the code. Anyone can type a untested TSQL statement in. However, I always stress testing to my team!
-- remove data
truncate table dwarfs;
go
-- add data
insert into dwarfs (full_name) values
('bilbo baggins'),
('gandalf the grey');
go
-- show the data
select * from dwarfs;
-- update data
update dwarfs
set full_name = 'gandalf'
where asigned_id = 2;
-- show the data
select * from dwarfs;
The output. I only waited 10 seconds between the insert and the delete. Nice thing is that who and when are both captured.
Create trigger tr_somename
On table_name
For update
As
Begin
Set nocount on;
Update t
Set t.field_name = getdate()
From table_name t inner join inserted I
On t.pk_column = I.pk_column
End
ALTER TRIGGER [trg_table_name_Modified]
ON [table_name]
AFTER UPDATE
AS
Begin
UPDATE table_name
SET modified_dt_tm = GETDATE() -- or use SYSDATETIME() for 2008 and newer
FROM Inserted i
WHERE i.ID = table_name.id
end

Trigger on insert and update that adds modification date

I'm making a simple table with names, emails etc, but I also have a ModifiedDate. My idea is to use a trigger after both insert and update, and insert the current date. Thus if anyone does anything (except delete) to that column, the date should reflect that.
This is however not working.
CREATE TRIGGER ModDate
ON X
AFTER INSERT, UPDATE
AS
BEGIN
INSERT INTO X (ModifiedDate)
VALUES (GETDATE())
END
Now I have a couple of values that can't be null, and what this seems to do is try and create a new row. I would like it to insert the date into the row that is currently being acted upon, I have no idea how though. Also what if I add 5 rows at once ?
You need to join the inserted virtual table in the trigger to limit the rows that get updated to those actually changed. Try this:
CREATE TRIGGER ModDate
ON TableX
AFTER INSERT, UPDATE
AS
BEGIN
UPDATE X
SET ModifiedDate = GETDATE()
FROM TableX X
JOIN inserted i ON X.key = i.key -- change to whatever key identifies
-- the tuples
END
Like #ZoharPeled correctly pointed out in a comment below there's really not much point in having the trigger update the date on insert - it would be better to use getdate() as the default value on the column (or even as another column InsertedDate if you want to track when records were initially created) and have the trigger only modify the ModifiedDate column after updates.
See the documentation for more information on the inserted and deleted tables.
CREATE TRIGGER ModDate
ON TableX
FOR INSERT, UPDATE
AS
BEGIN
UPDATE TableX
SET ModifiedDate = GETDATE()
WHERE Id = (Select Id from Inserted)
END
If you don't have keys on the insert data and you are not in command of the sql to add a default on the modifieddate column, you can get the insert trigger where the modifieddate column is null:
CREATE TRIGGER ModDate
ON TableX
AFTER INSERT
AS
BEGIN
UPDATE tableX SET ModifiedDate = GETDATE() where modifieddate is null
END

Trigger to update lastModified column automatically in MSSQL server using scope_identity()

I'm trying to create a trigger that automatically updates a column for an entry in my table when that specific entry is updated.
The table name is "accounts". The column name is "modified" (it is a dateTime that states when this entry was last updated).
I am using SCOPE_IDENTITY() to point to the entry which I wish to update.
The trigger is created successfully, but when I update an entry, the column "modified" does not change. perhaps I'm using SCOPE_IDENTITY() incorrectly? Here is my code:
CREATE TRIGGER trg_UpdateModified
ON dbo.accounts
AFTER UPDATE
AS
UPDATE dbo.accounts
SET modified = GETDATE()
WHERE sysID = SCOPE_IDENTITY()
Thanks!!
Use the inserted table to tell you which row(s) have just been updated:
CREATE TRIGGER trg_UpdateModified
ON dbo.accounts
AFTER UPDATE
AS
IF UPDATE(modified) RETURN; --Don't react recursively
UPDATE dbo.accounts
SET modified = GETDATE()
WHERE sysID in (select sysID from inserted)

Automatic Adding Current DateTime In TableField

I am using SQL SERVER 2005 and i am also newbie to SQL SERVER
now i need to know that is there any way or any technique in SQL SERVER 2005
such that as soon as i add new record in table then current date-time should be added in to any given field of table.
Example:
Suppose i have CUSTOMER table
and it has fields say CustomerID,CustomerName,....,DateTime.
now whenever new customer added in this table then current date-time should be automatically added in to DateTime Field of CUSTOMER table.
In SSMS one can set the Default value or binding property of the appropriate column of the table property to getdate().
You need to add default constraint:
alter table MyTable add constraint MyColumnDefault default getdate() for MyColumn;
I'm not much of an expert in SQL but you could use TIMESTAMP for this, see:
http://msdn.microsoft.com/en-us/library/ms182776%28v=sql.90%29.aspx
It sounds like you should have a look at the timestamp data type:
http://msdn.microsoft.com/en-us/library/ms182776%28v=sql.90%29.aspx
Check table definition with default value
Declare #Table Table
(
Id int identity,[Name] varchar(100),CreatedDate DateTime default (Getdate())
)
insert into #Table([Name])
values ('yogesh')
insert into #Table ([Name])
values ('Bhadauriya')
insert into #Table ([Name])
values ('Yogesh Bhadauriya')
select *
From #Table

What's the easiest way to add automatic version information to MSSQL tables?

The information should be 2 date time columns(inserted/updated) with ms precision and should be automatically updated by the server whenever someone inserts, or updates a row.
Add columns to your table
ALTER TABLE yourTable ADD
Inserted datetime NULL,
Updated datetime NULL
GO
Create an Update and Insert Trigger to update the columns
CREATE TRIGGER yourTableInsertTrigger
ON yourTable
AFTER INSERT
AS
BEGIN
Update yourTable Set Inserted = getdate()
from Inserted
Where yourTable.Key = Inserted.Key
END
GO
CREATE TRIGGER yourTableUpdateTrigger
ON yourTable
AFTER UPDATE AS
BEGIN
Update yourTable Set Updated = getdate()
from Updated
Where yourTable.Key = Updated.Key
END
GO
Now if you want to be really clean, you'd make sure that these two columns couldn't be changed/updated by using views instead of direct table access for your other access to the data. Also if your primary keys aren't consistent, and you have many tables I'd suggest you use CodeGeneration to create the sql. MyGeneration would do nicely.
I think the inserted trigger is obsolete. Just add getdate() to the inserted column as a default value instead of null.

Resources