2014-01-10 51 views
1

我正在寻找在SQL Server表中添加2个或更多列并使用总和更新另一列的最佳方法。如何最好总结2列和更新第3列总和?

是的,我知道这是一个愚蠢的事情,计算应该在交易时完成,但我正在修改现有的表,其中一列中的数据现在需要更详细,但大量的过程仍然会使用列值。

例如,列名是TotalDailyMiles,许多进程访问和使用该字段。现在需要更多细节。需要将2列添加到表TotalAMMiles和TotalPMMiles中。这2列将总和到现有列。将所有访问TotalDailyMiles列的进程改为使用2个新列不是一种选择。旧记录中新列的数据不存在,因此包含2个新列的总和的列的值不能基于旧记录中的2个新列,因为在旧记录中,新列值将为0,或者可能为null,但我倾向于0,所以我可以将新列设置为Not Null。

我在考虑使用触发器来更新基于新列更改列的总和,但我希望你们中的一个聪明的人有一个更好的选择。

+0

触发器绝对是这里走的路。我会害怕分裂列中的两个零和总数不匹配。也许至少用一个值填充一个,另一个用0填充,所以任何新的代码也可以工作。 – Randy

+1

@Randy imho,触发器不是要走的路。看到我的答案。 – ErikE

回答

2

将现有列作为自己的值处理(在未来的行中将为0),添加两个新列,然后创建一个与旧的Total相同名称的计算列?像这样的东西(我假设的decimal(7, 2)数据类型,但是当然可以用你所拥有的,但我希望这不是float):

EXEC sp_rename 'dbo.Miles.TotalDailyMiles', 'DailyMiles'; 
ALTER TABLE dbo.Miles ADD COLUMN AMMiles decimal(7, 2) NOT NULL 
    CONSTRAINT DF_Miles_AMMiles DEFAULT (0); 
ALTER TABLE dbo.Miles ADD COLUMN PMMiles decimal(7, 2) NOT NULL 
    CONSTRAINT DF_Miles_PMMiles DEFAULT (0); 
ALTER TABLE dbo.Miles ADD COLUMN TotalDailyMiles 
    AS (DailyMiles + AMMiles + PMMiles) PERSISTED; 

一些可能的管家,可能需要在DailyMiles柱,太:

-- if not already NOT NULL 
ALTER TABLE dbo.Miles ALTER COLUMN AMMiles decimal(7, 2) NOT NULL; 
-- if not already defaulting to 0 
ALTER TABLE dbo.Miles ADD 
    CONSTRAINT DF_Miles_DailyMiles DEFAULT (0) FOR DailyMiles; 

你可以另加要么DailyMiles必须为0,或AMMilesPMMiles约束都必须是0:

ALTER TABLE dbo.Miles ADD CONSTRAINT CK_Miles_DailyOrAMPM 
    CHECK (DailyMiles = 0 OR (AMMiles = 0 AND PMMiles = 0)); 

只要数据的使用者不尝试更新TotalDailyMiles列,您已经方便地解决了您的问题。

+0

+1。不知道如果添加的列有空值会发生什么情况。您可能需要编辑计算以使用'COALESCE(col,0.0)' –

+0

这很好。但我仍然会用触发器 - 同样 - 我会为将来的编码者看到所有这些列感到不好,并且必须弄清楚在哪种情况下在哪一列插入什么。 – Randy

+1

@Randy - 这就是业务规则和文档的来源。如果未来的编码人员不知道要插入什么列,他就没有业务处理表格。如果编码员是脆弱的,那么你提出的三个专栏的简单介绍会不会令人困惑?无论如何,“AMMiles”和“PMMiles”究竟会出现什么问题?如果在你的情况下,事情会不同步,并且他们错误地运行代码'UPDATE dbo.Miles SET TotalDailyMiles = TotalAMMiles + TotalPMMiles'?经过充分考虑,我仍然推荐这一点。 – ErikE