Reputation: 23
For reasons too silly to explain I have three columns in a table which hold date and time values. One column only holds the date, the second only holds the time, and the third holds a DATETIME
value. Looks like this:
OPPORTUNITYID | ... | ProductionDate | ProductionTime | PRODUCTIONDATETIME
-------------------------------------------------------------------------------
091798-324971 | ... | 12-07-2014 | 11:30 AM | 2014-07-12 11:30:00:000
Then I have a trigger that keeps these values in sync regardless of which is being updated. This is (part of) the trigger:
CREATE TRIGGER [dbo].[TBL_OPPORTUNITY_DUEDATES_TRU]
ON [dbo].[TBL_OPPORTUNITY]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF UPDATE ( PRODUCTIONDATETIME )
BEGIN
UPDATE TBL_OPPORTUNITY
SET ProductionDate = CONVERT(VARCHAR(10), PRODUCTIONDATETIME, 105)
, ProductionTime = REPLACE(REPLACE(RIGHT('0'+LTRIM(RIGHT(CONVERT(VARCHAR, PRODUCTIONDATETIME,100), 7)), 7), 'AM', ' AM'), 'PM', ' PM')
WHERE OPPORTUNITYID IN ( SELECT i.OPPORTUNITYID FROM inserted i
INNER JOIN deleted d ON i.OPPORTUNITYID = d.OPPORTUNITYID
WHERE NOT i.PRODUCTIONDATETIME = d.PRODUCTIONDATETIME
AND NOT ( i.PRODUCTIONDATETIME = '' OR i.PRODUCTIONDATETIME IS NULL )
);
END
IF ( UPDATE ( ProductionDate ) OR UPDATE ( ProductionTime ) )
BEGIN
UPDATE TBL_OPPORTUNITY
SET PRODUCTIONDATETIME = CONVERT(DATETIME, ProductionDate + ' ' + ProductionTime, 105)
WHERE OPPORTUNITYID IN ( SELECT i.OPPORTUNITYID FROM inserted i
INNER JOIN deleted d ON i.OPPORTUNITYID = d.OPPORTUNITYID
WHERE ( NOT i.ProductionDate = d.ProductionDate
OR NOT i.ProductionTime = d.ProductionTime )
AND NOT ( i.ProductionDate = '' OR i.ProductionDate IS NULL )
AND NOT ( i.ProductionTime = '' OR i.ProductionTime IS NULL )
);
UPDATE TBL_OPPORTUNITY
SET PRODUCTIONDATETIME = CONVERT(DATETIME, ProductionDate + ' 12:00:00', 105)
WHERE OPPORTUNITYID IN ( SELECT i.OPPORTUNITYID FROM inserted i
INNER JOIN deleted d ON i.OPPORTUNITYID = d.OPPORTUNITYID
WHERE ( NOT i.ProductionDate = d.ProductionDate
OR NOT i.ProductionTime = d.ProductionTime )
AND NOT ( i.ProductionDate = '' OR i.ProductionDate IS NULL )
AND ( i.ProductionTime = '' OR i.ProductionTime IS NULL )
);
END
END
GO
The trigger works as expected whenever any of the values are updated. However, the trigger fails (as in doesn't make any changes) if a value is being updated from NULL
, or in other words, the old value in a column was NULL
and the new value is, for example '02-03-2014'.
Why is that?
The server is Microsoft SQL Server 2008 R2.
Thank you for any clues.
Upvotes: 2
Views: 4477
Reputation: 1
Do this for every column you are tracking
DECLARE @ProductionDate Date;
DECLARE @ProductionDateOld Date;
DECLARE @ProductionDateInd bit = 0; // you can use the indicator later to determine which field changed. if = 0 it didn't change, if 1 it did change
DECLARE @ProductionDateTime DateTime;
DECLARE @ProductionDateTimeOld DateTime;
DECLARE @ProductionDateTimeInd bit = 0;
SELECT @ProductionDate=ProductionDate FROM inserted i;
SELECT @ProductionDateOld = d.ProductionDate FROM deleted d;
if @ProductionDateOld <> @ProductionDate
@ProductionDateInd = 1;
if @ProductionDateOld IS NULL AND @ProductionDate IS NOT NULL
@ProductionDateInd = 1;
SELECT @ProductionDateTime=ProductionDateTime FROM inserted i;
SELECT @ProductionDateTimeOld = d.ProductionDateTime FROM deleted d;
if @ProductionDateTimeOld <> @ProductionDateTime
@ProductionDateTimeInd = 1;
if @ProductionDateTimeOld IS NULL AND @ProductionDateTime IS NOT NULL
@ProductionDateTimeInd = 1;
Then check if a value changed (I do this to only write to history/audit table if there truly is a change)
if (@ProductionDateInd = 1 OR
@ProductionDateInd = 1)
INSERT INTO TBL_OPPORTUNITY_DUEDATES_TRU (
ProductionDate,
ProductionDateInd,
ProductionDateTime,
ProductionDateTimeInd,
.
.
.
)
VALUES (
@ProductionDate,
@ProductionDateInd,
@ProductionDateTime,
@ProductionDateTimeInd,
.
.
.
)
Upvotes: 0
Reputation: 414
As it is written, the trigger has to ignore rows where the old values are NULL because an equality or inequality involving NULL can never evaluate to true. A WHERE condition such as NOT i.ProductionDate = d.ProductionDate
is never going to return any rows if d.ProductionDate is NULL, no matter what i.ProductionDate is. You would need to explicitly check the possibility that d.ProductionDate IS NULL
to handle the cases where d.ProductionDate has no value.
Upvotes: 1