4

I have the following trigger (along with others on similar tables) that sometimes fails to put data into the historic table. It should put data into a historic table exactly as it's inserted/updated and stamped with a date.

CREATE TRIGGER [dbo].[trig_UpdateHistoricProductCustomFields]
ON [dbo].[productCustomFields]
AFTER UPDATE,INSERT
AS 
BEGIN

IF ((UPDATE(data)))
BEGIN
SET NOCOUNT ON; 

DECLARE @date bigint
SET @date = datepart(yyyy,getdate())*10000000000+datepart(mm,getdate())*100000000+datepart(dd,getdate())*1000000+datepart(hh,getdate())*10000+datepart(mi,getdate())*100+datepart(ss,getdate())

INSERT INTO historicProductCustomFields (productId,customFieldNumber,data,effectiveDate) (SELECT productId,customFieldNumber,data,@date from inserted)

END
END

Schema:

CREATE TABLE [dbo].[productCustomFields](
[id] [int] IDENTITY(1,1) NOT NULL,
[productId] [int] NOT NULL,
[customFieldNumber] [int] NOT NULL,
[data] [varchar](50) NULL,
 CONSTRAINT [PK_productCustomFields] PRIMARY KEY CLUSTERED 
(
[id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [dbo].[historicProductCustomFields](
[id] [bigint] IDENTITY(1,1) NOT NULL,
[productId] [int] NOT NULL,
[customFieldNumber] [int] NOT NULL,
[data] [varchar](50) NULL,
[effectiveDate] [bigint] NOT NULL,
 CONSTRAINT [PK_historicProductCustomFields] PRIMARY KEY CLUSTERED 
(
[id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON,     ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

I insert and update only on one record at a time on the productCustomFields table. It seems to work 99% of the time and hard to test for failure. Can anyone shed some light on what I may be doing wrong or better practices for this type of trigger?

Environment is Sql Server Express 2005. I haven't rolled out the service pack yet for sql server either for this particular client.

Luke Hutton
  • 10,612
  • 6
  • 33
  • 58
  • Looks like it should work to me. Is the `data` column definitely being set in all `UPDATE` calls? – Martin Smith Apr 09 '11 at 23:34
  • @Martin, yes, there are some cases when there are string values "123" in the data column in the productCustomFields table yet nothing in the historic table.. hard to debug – Luke Hutton Apr 09 '11 at 23:43
  • You definitely don't have a table called `historicProductCustomFields` in another schema? What is the definition of the archive table? It doesn't have a unique index with `IGNORE_DUP_KEY` option on? – Martin Smith Apr 09 '11 at 23:49
  • Definitely no other table in another schema. I've updated to include schema of the archive table. The id is set to auto increment. – Luke Hutton Apr 10 '11 at 00:30
  • @Luke - Can't see any reason why that wouldn't work. Are there any gaps in the `historicProductCustomFields` identity sequence that might indicate rows were deleted (though these could also be caused by errored transactions). Do you know whether you are missing `inserts`,`updates` or both? – Martin Smith Apr 10 '11 at 00:39
  • @Martin, I will do some more analysis and get back but at a first glance, I do see a gap where ID jumped up five higher than the previous record. Perhaps this could be from an errored transaction. Looks like I am missing the update. I will dig deeper. Thanks for the help thus far. – Luke Hutton Apr 10 '11 at 00:51
  • I know it's probably too late to change it, but what's the thinking behind storing the date in a bigint (as opposed to, say, a datetime column)? – Damien_The_Unbeliever Apr 10 '11 at 07:40
  • @Damien, this was something done before I started on the project so out of my hands, a huge convert script might help one day, but for now I don't see any immediate issues – Luke Hutton Apr 12 '11 at 17:10
  • I've added an additional insert into the historic table for now (duplicates ok), but still investigating and might add error logging in the trigger to see if I can catch the problem – Luke Hutton Apr 12 '11 at 17:12

3 Answers3

1

I think the right way to solve this is keep a TRY CATCH block when inserting into the dbo.historicProductCustomFields table and write the errors into a custom errorlog table. From there it is easy to track this down.

I also see a PK on the historicProductCustomFields table but if you insert and update a given record in ProductCustomFields table then won't you get primary key violations on the historicProductCustomFields table?

Sankar Reddy
  • 1,499
  • 9
  • 10
  • If there is an error in the trigger the modification would be rolled back as well surely. And the OP's PK is on an identity column in `historicProductCustomFields` so the answer to the question in your last sentence is clearly "No". – Martin Smith Apr 10 '11 at 23:27
  • Thanks, I may add a try catch in the trigger and log the error like this: [Logging error in triggers](http://stackoverflow.com/questions/2809659/logging-into-table-in-sql-server-trigger). As Martin said, I won't get PK violations. – Luke Hutton Apr 12 '11 at 17:08
0

You should schema qualify your table that you are inserting into. You should check to ensure that there are not multiple triggers on the table, as if there are, only 1 trigger for that type of trigger will fire and if there are 2 defined, they are run in random order. In other words, 2 triggers of the same type (AFTER INSERT) then one would fire and the other would not, but you don't necessary have control as to which will fire.

Ben Miller
  • 32
  • 1
  • Ben, can you provide a reference for this? I've never heard of it happening and I thought you could have multiple triggers and could even control the firing order using sp_settriggerorder. – Scott Bruns Jun 09 '11 at 23:36
0

try to use this trigger. i just give you example try to write trigger with this trigger.

create TRIGGER [dbo].[insert_Assets_Tran]
ON [dbo].[AssetMaster]
AFTER INSERT , UPDATE
AS BEGIN
DECLARE @isnum TINYINT;

SELECT @isnum = COUNT(*) FROM inserted;

IF (@isnum = 1)
INSERT INTO AssetTransaction
select [AssetId],[Brandname],[SrNo],[Modelno],[Processor],[Ram],[Hdd],[Display],[Os],[Office],[Purchasedt] ,[Expirydt],[Vendor],[VendorAMC],[Typename],[LocationName],[Empid],[CreatedBy],[CreatedOn],[ModifiedBy] ,[ModifiedOn],[Remark],[AssetStatus],[Category],[Oylstartdt],[Oylenddt],[Configuration] ,[AStatus],[Tassign]

FROM inserted;
ELSE
RAISERROR('some fields not supplied', 16, 1)
WITH SETERROR;
END

lucky One
  • 159
  • 5
  • 15