由于理由太愚蠢无法解释我在表中有三列保存日期和时间值。一列仅保存日期,第二列仅保留时间,第三列保留DATETIME
值。看起来像这样:
OPPORTUNITYID | ... | ProductionDate | ProductionTime | PRODUCTIONDATETIME
-------------------------------------------------------------------------------
091798-324971 | ... | 12-07-2014 | 11:30 AM | 2014-07-12 11:30:00:000
然后我有一个触发器,无论哪个值正在更新,这些值都保持同步。 这是触发器的一部分:
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
每当更新任何值时,触发器都会按预期工作。但是,如果正在从NULL
更新某个值,或者换句话说,列中的旧值为NULL
,则触发器会失败(如不进行任何更改)值是,例如' 02-03-2014'。
为什么?
服务器是Microsoft SQL Server 2008 R2。
感谢您提供任何线索。
答案 0 :(得分:1)
在编写时,触发器必须忽略旧值为NULL的行,因为涉及NULL的相等或不等式永远不能求值为true。如果d.ProductionDate为NULL,那么诸如NOT i.ProductionDate = d.ProductionDate
之类的WHERE条件永远不会返回任何行,无论i.ProductionDate是什么。您需要明确检查d.ProductionDate IS NULL
处理d.ProductionDate没有值的情况的可能性。
答案 1 :(得分:0)
为您要跟踪的每个列执行此操作
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;
然后检查值是否已更改(如果确实存在更改,我这样做只会写入历史/审计表)
if (@ProductionDateInd = 1 OR
@ProductionDateInd = 1)
INSERT INTO TBL_OPPORTUNITY_DUEDATES_TRU (
ProductionDate,
ProductionDateInd,
ProductionDateTime,
ProductionDateTimeInd,
.
.
.
)
VALUES (
@ProductionDate,
@ProductionDateInd,
@ProductionDateTime,
@ProductionDateTimeInd,
.
.
.
)