2013-10-25 39 views
0

我有一个包含“购买日期”和“保修期限”列的计算机表。我希望每台计算机(行)将“购买日期”中的日期值添加4年,并将结果放入“保修期限”列中。我还希望在创建新计算机时自动发生此情况,并尽可能输入其购买日期。Microsoft SQL 2012基于列值的日期差异

感谢

回答

6

删除列,并使其计算:

ALTER TABLE dbo.TableName DROP COLUMN WarrantyExpires; 

ALTER TABLE dbo.TableName ADD WarrantyExpires 
    AS CONVERT(DATE, DATEADD(YEAR, 4, DatePurchased)); 

或者更好的,甚至不存储此。由于每行都是一样的(假设您没有4年的保证),只需在运行时执行计算即可。

如果每行都不一样,或者客户可以(现在或以后)延长保修期,那么计算列是不可行的。相反:

ALTER TABLE dbo.TableName ADD WarrantyExpires DATE; 

然后一个INSTEAD OF触发也许它依赖于由插入(你会用它来重写),四年自购买日起提供的值(如果提供的到期日没有价值填充)。所以:

CREATE TRIGGER dbo.FixWarrantyDate 
ON dbo.TableName 
INSTEAD OF INSERT 
AS 
BEGIN 
    SET NOCOUNT ON; 

    INSERT dbo.TableName(OrderID, /* other cols, */ DatePurchased, WarrantyExpires) 
    SELECT OrderID, /* other cols, */ COALESCE(DatePurchased,GETDATE()), 
     COALESCE(WarrantyExpires,DATEADD(YEAR,4,COALESCE(DatePurchased,GETDATE()))) 
    FROM inserted; 
END 
GO 

所以,现在你的基部插入看起来是这样的默认情况下:

INSERT dbo.TableName(OrderID, DatePurchased, WarrantyExpires) 
    SELECT 1, GETDATE(), NULL; 

-- or 

INSERT dbo.TableName(OrderID, DatePurchased) 
    SELECT 2, GETDATE(); 

-- or even: 

INSERT dbo.TableName(OrderID) SELECT 3; 

如果有人购买了延长保修期,你可以重写(或更高版本手动更新):在表

INSERT dbo.TableName(OrderID, DatePurchased, WarrantyExpires) 
    SELECT 4, GETDATE(), DATEADD(YEAR, 5, GETDATE()); 

所得数据这四个插入件后:

OrderID DatePurchased WarrantyExpires 
------- ------------- --------------- 
1   2013-10-25  2017-10-25 
2   2013-10-25  2017-10-25 
3   2013-10-25  2017-10-25 
4   2013-10-25  2018-10-25 

现在我觉得我也应该解释为什么我更喜欢INSTEAD OF触发器。虽然他们确实要求你重新写的INSERT语句,这将触发后不这样做,好处,他们补充:

  • 你处理你的业务逻辑后,也仍然可以执行插入(和更新一个后触发器通常处理)在一个单一的陈述。这对日志更友好。

  • 如果触发器中的业务逻辑可能会回滚事务,那么在触发器INSTEAD OF中这样做会好得多。影响日志,可能导致页面拆分,然后删除行,影响日志,添加需要稍后清理的幻影行,而不是写入行,影响日志,可能导致页面拆分,而不是执行插入。

+0

或有一个计算列:) – Schalk

+2

@Schalk是不是我的答案建议? –