Solved

trigger - if column updates, insert a record

Posted on 2014-11-17
17
293 Views
Last Modified: 2014-11-18
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
0
Comment
Question by:websss
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 5
  • 3
  • +2
17 Comments
 
LVL 13

Expert Comment

by:Koen Van Wielink
ID: 40446965
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
 
LVL 50

Expert Comment

by:Vitor Montalvão
ID: 40446993
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
 

Author Comment

by:websss
ID: 40447064
0
Business Impact of IT Communications

What are the business impacts of how well businesses communicate during an IT incident? Targeting, speed, and transparency all matter. Find out more in this infographic.

 

Author Comment

by:websss
ID: 40447067
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
 
LVL 34

Expert Comment

by:ste5an
ID: 40447068
Just a comment..

You've got a major design flaw in your model: An IMEI cannot change.
0
 

Author Comment

by:websss
ID: 40447071
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
 
LVL 34

Expert Comment

by:ste5an
ID: 40447074
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
 

Author Comment

by:websss
ID: 40447078
ste5an, ok pointless discussion since its irrelevant to the question
0
 
LVL 50

Expert Comment

by:Vitor Montalvão
ID: 40447081
@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
 

Author Comment

by:websss
ID: 40449154
oh i see
what code would you suggest i use?
0
 
LVL 50

Accepted Solution

by:
Vitor Montalvão earned 500 total points
ID: 40449199
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
 

Author Closing Comment

by:websss
ID: 40449248
Vitor you are a genius!
0
 
LVL 50

Expert Comment

by:Vitor Montalvão
ID: 40449255
Please, don't exaggerate :)
Thanks.
0
 
LVL 34

Expert Comment

by:ste5an
ID: 40449264
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
 
LVL 9

Expert Comment

by:Valliappan AN
ID: 40449273
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
 
LVL 50

Expert Comment

by:Vitor Montalvão
ID: 40449276
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
 

Author Comment

by:websss
ID: 40449288
correct... this table is rarely updated, and 1 at a time
0

Featured Post

DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

JSON is being used more and more, besides XML, and you surely wanted to parse the data out into SQL instead of doing it in some Javascript. The below function in SQL Server can do the job for you, returning a quick table with the parsed data.
International Data Corporation (IDC) prognosticates that before the current the year gets over disbursing on IT framework products to be sent in cloud environs will be $37.1B.
This video shows, step by step, how to configure Oracle Heterogeneous Services via the Generic Gateway Agent in order to make a connection from an Oracle session and access a remote SQL Server database table.
Via a live example combined with referencing Books Online, show some of the information that can be extracted from the Catalog Views in SQL Server.

729 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question