trigger - if column updates, insert a record

I am trying to create a trigger which inserts a record if a column name changes

so far i have this code:
USE [GPSOL]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER TRIGGER [dbo].[UpdatedImeiNumber]
ON [dbo].[Newtbl_DeviceMaster] -- table name
AFTER UPDATE
AS 
declare @imeiNumber as varchar(50) = ''

begin
IF EXISTS (
    SELECT
       I.nIMEINo
    FROM
        INSERTED I
        JOIN
        DELETED D
            -- make sure to compare inserted with (same) deleted IMEI
            ON D.nIMEINo = I.nIMEINo 
            AND D.nIMEINo <> I.nIMEINo -- only IMEI with changed name

    )  

	select @imeiNumber = (SELECT nIMEINo FROM   Inserted)

print 'inserting dummy record'
	insert into tblCommonTrackingData (vSequenceID, vpkDeviceID, dGPSDateTime)
	values('1', @imeiNumber, GETDATE())
	end

Open in new window


However, the IMEINumber is never being assigned from this line
select @imeiNumber = (SELECT nIMEINo FROM   Inserted)

Open in new window


the record is being inserted by the IMEI number is always blank
Also, the record is being inserted if i update other columns and not just IMEI number

what am i doing wrong
websssAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Koen Van WielinkBusiness Intelligence SpecialistCommented:
Looks like you're missing a BEGIN and END statement.

USE [GPSOL]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER TRIGGER [dbo].[UpdatedImeiNumber]
ON [dbo].[Newtbl_DeviceMaster] -- table name
AFTER UPDATE
AS 
declare @imeiNumber as varchar(50) = ''

begin
IF EXISTS (
    SELECT
       I.nIMEINo
    FROM
        INSERTED I
        JOIN
        DELETED D
            -- make sure to compare inserted with (same) deleted IMEI
            ON D.nIMEINo = I.nIMEINo 
            AND D.nIMEINo <> I.nIMEINo -- only IMEI with changed name

    )  
BEGIN

	select @imeiNumber = (SELECT nIMEINo FROM   Inserted)

print 'inserting dummy record'
	insert into tblCommonTrackingData (vSequenceID, vpkDeviceID, dGPSDateTime)
	values('1', @imeiNumber, GETDATE())
END
	end

Open in new window


You're evaluating an if statement to see if your record exists. That would explain why the record is always inserted, not just when the IMEI number is changed. I suspect the select statement isn't properly executed for the same reason.

You can rewrite your select statement for the variable like this:
Select @imeiNumber = nIMEINo
From Inserted

Open in new window

Maybe that's why the assignment isn't working as expected.
0
Vitor MontalvãoMSSQL Senior EngineerCommented:
I can't understand your join criteria. How can a record be equal and different at same time??
ON D.nIMEINo = I.nIMEINo AND D.nIMEINo <> I.nIMEINo
0
websssAuthor Commented:
0
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

websssAuthor Commented:
I did try having a nested begin end, but the record would not insert
...just tried your code and it didn't insert into the DB
0
ste5anSenior DeveloperCommented:
Just a comment..

You've got a major design flaw in your model: An IMEI cannot change.
0
websssAuthor Commented:
ste5an, you are correct but you can put a different sim card in a different phone
so you must update the table to say which IMEI the sim card is using
0
ste5anSenior DeveloperCommented:
A phone can have more than one IMEI..

and, my first statement was not correct. An IMEI can change. But much worse: 10% of the IMEIs in the 02 (BT Cellenet) were not unique.

So I have to change my my objection: An IMEI is a pretty ugly identifer for direct usage in a relational database.

But another problem: Triggers are executed per statement in SQL Server, thus your trigger will fail at select @imeiNumber = (SELECT nIMEINo FROM   Inserted).

Can you give us more context please?
0
websssAuthor Commented:
ste5an, ok pointless discussion since its irrelevant to the question
0
Vitor MontalvãoMSSQL Senior EngineerCommented:
@webss, if you verify in that example they aren't using the same column names:
ON D.ID = I.ID AND D.NAME <> I.NAME
as you can see they are using ID and Name, so will find records with same ID but different Names.
0
websssAuthor Commented:
oh i see
what code would you suggest i use?
0
Vitor MontalvãoMSSQL Senior EngineerCommented:
Let's review your question then.
I am trying to create a trigger which inserts a record if a column name changes
To be more accurate, is not when a column name changes but when occurs a record update.

However, the IMEINumber is never being assigned from this line
(...)
the record is being inserted by the IMEI number is always blank
Yes, because the previous SELECT won't return any records because of the WHERE clause isn't correct.

Also, the record is being inserted if i update other columns and not just IMEI number
Of course. The UPDATE trigger fires when any of the columns is updated and not only a specific one.

Try this code:
USE [GPSOL]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER TRIGGER [dbo].[UpdatedImeiNumber]
ON [dbo].[Newtbl_DeviceMaster] -- table name
AFTER UPDATE
AS 
begin
        declare @imeiNumber as varchar(50) = ''
	select @imeiNumber = (SELECT nIMEINo FROM   Inserted)

        -- Check if the IMEI was changed
        IF NOT EXISTS (
                  SELECT 1
                 FROM DELETED
                  WHERE nIMEINo = @imeiNumber )  

	        insert into tblCommonTrackingData (vSequenceID, vpkDeviceID, dGPSDateTime)
           	values('1', @imeiNumber, GETDATE())
end

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
websssAuthor Commented:
Vitor you are a genius!
0
Vitor MontalvãoMSSQL Senior EngineerCommented:
Please, don't exaggerate :)
Thanks.
0
ste5anSenior DeveloperCommented:
As I already wrote, this kind of trigger is erroneous. Triggers are executed per statement.

USE tempdb;
GO

CREATE TABLE dbo.Newtbl_DeviceMaster ( nIMEINo INT );
CREATE TABLE dbo.tblCommonTrackingData
    (
      vSequenceID VARCHAR(255) ,
      vpkDeviceID VARCHAR(255) ,
      dGPSDateTime DATE
    );
GO

CREATE TRIGGER dbo.UpdatedImeiNumber ON dbo.Newtbl_DeviceMaster
    AFTER UPDATE
AS
    BEGIN
        DECLARE @imeiNumber AS VARCHAR(50) = '';

        SELECT  @imeiNumber = ( SELECT  nIMEINo
                                FROM    Inserted
                              );

        -- Check if the IMEI was changed
        IF NOT EXISTS ( SELECT  1
                        FROM    DELETED
                        WHERE   nIMEINo = @imeiNumber )
            INSERT  INTO dbo.tblCommonTrackingData
                    ( vSequenceID ,
                      vpkDeviceID ,
                      dGPSDateTime
                    )
            VALUES  ( '1' ,
                      @imeiNumber ,
                      GETDATE()
                    )
    END;
GO

INSERT  INTO Newtbl_DeviceMaster
        ( nIMEINo )
VALUES  ( 1 ),
        ( 2 ),
        ( 3 );
GO

SELECT  *
FROM    dbo.Newtbl_DeviceMaster;

UPDATE  T
SET     nIMEINo = nIMEINo + 10
FROM    Newtbl_DeviceMaster T
WHERE   T.nIMEINo IN ( 2, 3 );

SELECT  *
FROM    dbo.Newtbl_DeviceMaster;

SELECT  *
FROM    dbo.tblCommonTrackingData TCTD;
GO

DROP TABLE dbo.Newtbl_DeviceMaster;
DROP TABLE dbo.tblCommonTrackingData;
GO

Open in new window


Thus it will fail with:

(3 row(s) affected)

(3 row(s) affected)
Msg 512, Level 16, State 1, Procedure UpdatedImeiNumber, Line 8
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
The statement has been terminated.

Open in new window

0
Valliappan ANSenior Tech ConsultantCommented:
You could also use IF UPDATE(Imei_Number) while updating, to do the update, only when, this field is updated, and not otherwise.

My 2 cents.
HTH.
0
Vitor MontalvãoMSSQL Senior EngineerCommented:
Sure, the solution I gave only works for one record been updated. But the author didn't say nothing about massive updates. For that the solution should be a little bit different.
0
websssAuthor Commented:
correct... this table is rarely updated, and 1 at a time
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft SQL Server

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.