Ideally you should be using computed columns as per Do you use computed columns rather than denormalized fields?
You can also have a denormalized field that is manually updated. This should be the exception and not the rule. When used properly and sparingly, they can actually improve your application's performance.
As an example:
To generate this report, you can either:
The second option will save me an expensive JOIN query each time because you can just tack the denormalised field onto the end of my SELECT query.
1. Code: Alter Orders table
ALTER TABLE OrdersADD SumOfOrderItems money NULL
Alter Trigger tri_SumOfOrderItemsOn dbo.OrderItemsFor InsertASDECLARE @OrderID varchar (5)SELECT @OrderID = OrderID from insertedUPDATE OrdersSET Orders.SumOfOrderItems = Orders.SumOfOrderItems +(SELECT isnull(SUM(ItemValue),0) FROM inserted WHERE inserted.OrderID = Orders.OrderID)WHERE Orders.OrderID = @OrderID
Alter Trigger tru_SumOfOrderItemsOn dbo.OrderItemsFor UpdateASDECLARE @OrderID varchar (5)SELECT @OrderID = OrderID from deleted--Could have used inserted tableUPDATE OrdersSET Orders.SumOfOrderItems = Orders.SumOfOrderItems+ (SELECT isnull(SUM(ItemValue),0) FROM inserted WHERE inserted.OrderID = Orders.OrderID)- (SELECT isnull(SUM(ItemValue),0) FROM deleted WHERE deleted.OrderID = Orders.OrderID)WHERE Orders.OrderID = @OrderID
Alter Trigger trd_SumOfOrderItemsOn dbo.OrderItemsFor DeleteASDECLARE @OrderID varchar (5)SELECT @OrderID = OrderID FROM deletedUPDATE OrdersSET Orders.SumOfOrderItems = Orders.SumOfOrderItems -(SELECT isnull(SUM(ItemValue),0) FROM deleted WHERE deleted.OrderID = Orders.OrderID)WHERE Orders.OrderID = @OrderID
--Stored Procedure for MaintenanceAlter Procedure dt_Maintenance_SumOfItemValueAsUPDATE OrdersSET Orders.SumOfOrderItems = Isnull((SELECT SUM (ItemValue) FROM OrderItems WHERE OrderItems.OrderID = Orders.OrderID),0)