我有一个包含“已购买日期”和“保修期限”的列的计算机表。我希望每台计算机(行)在“购买日期”中将其日期值加上4年,并将结果放在“保修期限”列中。我也希望在创建新计算机并在可能的情况下输入其购买日期时自动发生。
由于
答案 0 :(得分: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
触发器中执行此操作会好得多。而不是写行,影响日志,可能导致页面拆分,然后删除行,影响日志,并添加需要稍后清理的幻影行,您只需挽救并且根本不执行插入。 / p>