Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2008 Forums
 Transact-SQL (2008)
 Trouble Creating AFTER INSERT Trigger

Author  Topic 

chillbeast
Starting Member

5 Posts

Posted - 2010-02-05 : 19:11:06
No matter what I do, I can't get this trigger to fire without failing. I've tested all my SQL statements separately and they all are valid. Seems like it is doing the auto-rollback thing whenever the trigger fires though. Any help is appreciated.

Here is my trigger:

USE [MyDatabaseName]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[customer_trigger_INSERT]
ON [dbo].[Customer]
AFTER INSERT
AS

IF EXISTS (SELECT * FROM EmailContacts WHERE Email=(SELECT Email FROM inserted))
BEGIN
UPDATE EmailContacts
SET Name = (SELECT FirstName + ' ' + LastName FROM inserted)
WHERE Email = (SELECT Email FROM inserted)
END
ELSE
BEGIN
INSERT INTO EmailContacts (Email, Name)
SELECT FirstName + ' ' + LastName, Email FROM inserted
END;


It's supposed to update the EmailContacts table with the customers name and email and insert if they don't exist over there yet.

Thanks in advance!
-josh

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2010-02-05 : 20:10:56
Try this:


ALTER TRIGGER [dbo].[customer_trigger_INSERT]
ON [dbo].[Customer]
FOR INSERT
AS

UPDATE e
SET Name = i.FirstName + ' ' + i.LastName
FROM EmailContacts e
JOIN inserted i
ON e.Email = i.Email

IF @@ROWCOUNT = 0
INSERT INTO EmailContacts (Email, Name)
SELECT FirstName + ' ' + LastName, Email
FROM inserted


You need to use a JOIN to the inserted trigger table since a trigger fires for the entire INSERT and not just one row at a time. See this for more information: http://weblogs.sqlteam.com/tarad/archive/2004/09/14/2077.aspx

Tara Kizer
Microsoft MVP for Windows Server System - SQL Server
http://weblogs.sqlteam.com/tarad/

Subscribe to my blog

"Let's begin with the premise that everything you've done up until this point is wrong."
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2010-02-06 : 02:10:29
I think there is a risk that some rows, but not all, might exist in EmailContacts, so I would go for a variation on Tara's suggestion:

UPDATE e
SET Name = i.FirstName + ' ' + i.LastName
FROM EmailContacts e
JOIN inserted i
ON e.Email = i.Email
WHERE Name <> i.FirstName + ' ' + i.LastName

INSERT INTO EmailContacts (Email, Name)
SELECT Email, FirstName + ' ' + LastName
FROM inserted AS I
WHERE NOT EXISTS
(
SELECT *
FROM EmailContacts AS E
WHERE E.Email = I.Email
)


Note also that you appear to have got your columns the wrong way round on your INSERT (may just have been cut & paste error to make your post here though)

Edit: Added an optimisation to UPDATE to not update where there is no change.
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2010-02-06 : 02:12:11
P.S. Is it ever possible for either FirstName or LastName to be NULL? If so you need to concatenate them using:

NullIf(RTrim(COALESCE(FirstName + ' ', '') + COALESCE(LastName, '')), '')
Go to Top of Page

chillbeast
Starting Member

5 Posts

Posted - 2010-02-08 : 12:00:15
thanks for the assistance Tara & Kristen,
Here is what I have now:


ALTER TRIGGER [dbo].[customer_trigger_INSERT]
ON [dbo].[Customer]
FOR INSERT
AS

UPDATE e
SET Name = i.FirstName + ' ' + i.LastName
FROM EmailContacts e
JOIN inserted i
ON e.Email = i.Email
WHERE Name <> i.FirstName + ' ' + i.LastName

INSERT INTO EmailContacts (Email, Name)
SELECT Email, FirstName + ' ' + LastName
FROM inserted AS I
WHERE NOT EXISTS
(
SELECT *
FROM EmailContacts AS E
WHERE E.Email = I.Email
)


It's still rolling back the entire INSERT. Could it be related to the fact that this gets triggered by a Stored Procedure? Unfortunately I am unable to modify the stored proc which would be much easier to accomplish this.
Any other ideas/thoughts are greatly appreciated.

-Josh
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2010-02-08 : 12:08:41
"Could it be related to the fact that this gets triggered by a Stored Procedure?"

Only if the SProc (or some outer process) does a ROLLBACK. But then the changes would not be stored in your Customer table either.

Are you saying that if you drop this trigger you can use the Sproc to change a Customer record, but if you Create this trigger then you can NOT change a Customer Record with the Sproc (i.e. it rolls back)?

What happens if you do something like:

BEGIN TRANSACTION

INSERT INTO dbo.Customer(FirstName, LastName, Email)
VALUES('Kristen', 'Netsirk', 'kristen@example.com')

SELECT TOP 10 * FROM dbo.Customer WHERE Email = 'kristen@example.com'

SELECT TOP 10 * FROM dbo. EmailContacts WHERE Email = 'kristen@example.com'

ROLLBACK

this won't actually generate a row insert (because of the ROLLBACK), so you will either get an error (which will hopefully shed more light on the problem), or you will see something from the two SELECT statements (in which case the trigger is working fine, and there is indeed some issue with the SProc not liking your trigger)

Another possibility is that you need more columns in the INSERT statement (e.g. for any columns that are NOT NULL) - in which case add more columns and some suitable data
Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2010-02-08 : 12:08:48
what about this?


ALTER TRIGGER [dbo].[customer_trigger_INSERT]
ON [dbo].[Customer]
FOR INSERT
AS
BEGIN

UPDATE e
SET Name = i.FirstName + ' ' + i.LastName
FROM EmailContacts e
JOIN inserted i
ON e.Email = i.Email
WHERE Name <> i.FirstName + ' ' + i.LastName

INSERT INTO EmailContacts (Email, Name)
SELECT I.Email, I.FirstName + ' ' + I.LastName
FROM inserted AS I
LEFT JOIN EmailContacts AS E
ON E.Email = I.Email
WHERE E.Email IS NULL
END

Go to Top of Page

chillbeast
Starting Member

5 Posts

Posted - 2010-02-08 : 12:33:24
quote:
Originally posted by Kristen

"Could it be related to the fact that this gets triggered by a Stored Procedure?"

Only if the SProc (or some outer process) does a ROLLBACK. But then the changes would not be stored in your Customer table either.

Are you saying that if you drop this trigger you can use the Sproc to change a Customer record, but if you Create this trigger then you can NOT change a Customer Record with the Sproc (i.e. it rolls back)?

What happens if you do something like:

BEGIN TRANSACTION

INSERT INTO dbo.Customer(FirstName, LastName, Email)
VALUES('Kristen', 'Netsirk', 'kristen@example.com')

SELECT TOP 10 * FROM dbo.Customer WHERE Email = 'kristen@example.com'

SELECT TOP 10 * FROM dbo. EmailContacts WHERE Email = 'kristen@example.com'

ROLLBACK

this won't actually generate a row insert (because of the ROLLBACK), so you will either get an error (which will hopefully shed more light on the problem), or you will see something from the two SELECT statements (in which case the trigger is working fine, and there is indeed some issue with the SProc not liking your trigger)




I believe this is the case as I did see results from the trigger when I used your SQL statements above to test. I also noticed that the ID field which is autoincrementing is up to 563 when the next lowest in the DB is 501, so all these tests I've been doing have been triggering properly, something else is causing it to mess up. Now I'm at a loss of what to do next as I cannot make any changes to the stored procedure. Unfortunately I might have to add code to every web form that can possibly modify the customer table to reflect those changes on the emailcontacts table.

Thanks again for your help, especially Kristen. Hopefully I can get something working :)

-Josh
Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2010-02-08 : 12:36:37
is there a chance of any other triggers(instead of ) existing on tables EmailContacts or Customer which might be doing something against save action?
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2010-02-08 : 12:40:51
Well I'll be blowed. Can't imagine what the Sproc could possibly be doing that could trip up on this. But there is always something to catch us out of course ...

Right ...

You could look at the SProc:

sp_HelpText TheCannotBeChangedSProcName

and see if you can see any code that is rolling back the transaction and if so under what circumstances it does it.

One possibility is that it is getting the IDENTITY number using @@IDENTITY (which is now old hat, and outdated - it should be using SCOPE_IDENTITY() ), and that may be getting the IDENTITY from your insert into EmailContacts (assuming that has an IDENTITY column), then doing a Lookup and, not unreasonably, NOT finding the new record.

Does this have to be real time? Could you run a batch once an hour, or so, that freshened up EmailContacts where it was different to Customer table?
Go to Top of Page

chillbeast
Starting Member

5 Posts

Posted - 2010-02-08 : 12:42:05
This is actually the only trigger for the entire DB. It's a shopping cart system we use and everything is in stored procs.

I think I may actually be able to go ahead and change the stored proc to update both tables so I may end up just going that route.
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2010-02-08 : 12:46:58
I think it needs some investigation of what the Sproc is doing, because this trigger is about as benign as it is possible to be!
Go to Top of Page

chillbeast
Starting Member

5 Posts

Posted - 2010-02-08 : 13:10:50
The Sproc looks pretty straightforward, not really sure what would be causing a problem:

ALTER proc [dbo].[aspdnsf_insCustomer]
@Email nvarchar(100),
@Password nvarchar(100),
@SkinID int,
@AffiliateID int,
@Referrer ntext,
@IsAdmin tinyint,
@LastIPAddress varchar(40),
@LocaleSetting nvarchar(10),
@Over13Checked tinyint,
@CurrencySetting nvarchar(10),
@VATSetting int,
@VATRegistrationID nvarchar(100),
@CustomerLevelID int,
@CustomerID int OUTPUT

AS
SET NOCOUNT ON


insert dbo.Customer(CustomerGUID, CustomerLevelID, RegisterDate, Email, Password, DateOfBirth, Gender, FirstName, LastName, Notes, SkinID, Phone, AffiliateID, Referrer, CouponCode, OkToEmail, IsAdmin, BillingEqualsShipping, LastIPAddress, OrderNotes, SubscriptionExpiresOn, RTShipRequest, RTShipResponse, OrderOptions, LocaleSetting, MicroPayBalance, RecurringShippingMethodID, RecurringShippingMethod, BillingAddressID, ShippingAddressID, GiftRegistryGUID, GiftRegistryIsAnonymous, GiftRegistryAllowSearchByOthers, GiftRegistryNickName, GiftRegistryHideShippingAddresses, CODCompanyCheckAllowed, CODNet30Allowed, ExtensionData, FinalizationData, Deleted, CreatedOn, Over13Checked, CurrencySetting, VATSetting, VATRegistrationID, StoreCCInDB, IsRegistered, LockedUntil, AdminCanViewCC, PwdChanged, BadLoginCount, LastBadLogin, Active, PwdChangeRequired, SaltKey)
values
(
newid(),
@CustomerLevelID,
getdate(),
isnull(@Email, ''),
isnull(@Password, ''),
null,
null,
null,
null,
null,
isnull(@SkinID, 1),
null,
@AffiliateID,
@Referrer,
null,
1,
isnull(@IsAdmin, 0),
0,
@LastIPAddress,
null,
null,
null,
null,
null,
isnull(@LocaleSetting, ('en-US')),
0.0,
1,
null,
null,
null,
newid(),
1,
1,
null,
1,
0,
0,
null,
null,
0,
getdate(),
@Over13Checked,
@CurrencySetting,
@VATSetting,
@VATRegistrationID,
1,
0,
null,
1,
getdate(),
0,
null,
1,
0,
0
)

set @CustomerID = @@identity
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2010-02-08 : 13:26:18
"set @CustomerID = @@identity"

is the problem

Should be

set @CustomerID = SCOPE_IDENTITY( )

either the Sproc is very old, or the people that wrote it are not up-to-speed with the more subtle nuances of SQL Server
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2010-02-08 : 13:31:40
I'm not sure why that would cause a rollback, but probably something in the APP itself.

It is possible to work around this (i.e. FAKE the @@IDENTITY back to this Sproc, but that's a bit of a PITA if you can find another solution).

And another thing whilst I'm on my soap box all the:

isnull(@SomeParameter, '')

is really stupid IMHO.

NULL is a value specifically provided to indicate "unknown".

ISNULL() is converting NULL values to "blank".

If you store Blank, instead of NULL, you then have no way of differentiating between someone who was asked the question, and answered with a blank string, and another scenario where the user was never asked the question (which would legitimately be NULL).

Smells of "We don't know where we are getting NULLs from, so lets just stop them hitting the database"
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2010-02-08 : 13:38:33
Right! I'm really "off on one" now!

" @Email nvarchar(100), Not long enough for Emails
@Password nvarchar(100),
Who actually uses 100 character passwords?
@Referrer ntext,
Is this a free text field, or just a web referrer (in which case the length is finite, not infinite)
@LastIPAddress varchar(40),
40 character IP address? Current IP address is 15, IP6 is 23, allow for pan-galactic perhaps?
@Over13Checked tinyint,
Could be BIT ?
@CurrencySetting nvarchar(10),
Country code? 10 characters? UNICODE?
@VATRegistrationID nvarchar(100),
Well VAT has to be UK right? No way do we have 100 characters ..."
Go to Top of Page
   

- Advertisement -