solving sql server problems for millions of dbas and developers since 2006



SQL Server DBA Tips SQL Server Developer Tips SQL Server Business Intelligence Tips SQL Server Career Tips SQL Server Tip Categories SQL Server Tutorials SQL Server Webcasts SQL Server Whitepapers SQL Server Tools SQL Server Questions and Answers MSSQLTips Authors About MSSQLTips SQL Server User Groups MSSLQTips Giveaways MSSQLTips Advertising Options

MSSQLTips Facebook Page MSSQLTips LinkedIn Page MSSQLTips RSS Feed MSSQLTips Twitter Page MSSQLTips Google+ Page

SQL Product Highlight

Idera - SQL safe backup

Idera's SQL safe provides a high-performance backup and recovery solution for Microsoft SQL Server. SQL safe saves money by reducing database backup time by up to 50% over native backups and reducing backup disk space requirements by up to 95%. SQL safe also enables complete "hands-free" automated backup of your entire SQL Server infrastructure and ensures compliance with your organization's backup and recovery policies. From implementations with tens of SQL servers to enterprises with hundreds of servers spread around the globe, SQL safe is the only SQL Server backup and recovery solution that scales to meet the challenge.

Learn more!








Using Computed Columns in SQL Server with Persisted Values

By: | Read Comments (6) | Print

Atif is a passionate SQL Server DBA, technical reviewer and article author.

Related Tips: More
In my databases I had some values that were often calculated while generating several reports. Also there were some columns that were dependent on one or more other columns. As one column was updated triggers were being used to synchronize new values in dependent columns. I was required to provide a more efficient and standard approach to handle these types of scenarios. So how could I get rid of the overhead for calculations at report generation time and how could I avoid the use of triggers for synchronizing updated columns?

Solution
For such scenarios where calculated values are required or values are generated through manipulation on other columns, we have a powerful feature provided in SQL Server. This feature is "Computed Columns".

A computed column is computed from an expression that can use another column or columns in the same table. Functions, variables, constants, non computed column names or any combination of all these may be used along with operators to create a computed column. In this tip we will go through an example of implementing a computed column.

I have tested the scripts on SQL Server 2005 and SQL Server 2008. In the following script we will create a table called CCtest in the AdventureWorks database with three columns [empNumb], [DOBirth] , [DORetirement].

We are required to have the "Date of Retirement" for each employee as (DOBirth + 60 years - 1 day). Instead of calculating it each time in the report or updating the column [DORetirement] each time through a trigger when [DOBirth] is updated, we have a better approach here to create [DORetirement] as a computed column.  Since this rule could change at anytime we are implementing it as a computed column instead of a hard coded value.

Script # 1: Create a table with computed column
USE [AdventureWorks]
GO 
-- Create Table with computed column
CREATE TABLE [dbo].[CCtest]
(
[empNumb] [int] NULL,
[DOBirth] [datetime] NULL,
[DORetirement] AS (dateadd(year,(60),[DOBirth])-(1)) PERSISTED
)
GO

The same may be done through SSMS. Create new table by right clicking on the Tables folder in the AdventureWorks database.

You will be provided a design view for the new table in SSMS. Provide specifications for the calculated column as shown below.

Now we have our table CCtest with a computed column. Similarly we can add a computed column to any existing table using the "ALTER TABLE" command or opening the table in design view using SSMS and making the changes.

Let's insert some data and run a query to test the functionality of the computed column.

Script # 2: Insert data in table

USE AdventureWorks
GO 
INSERT INTO CCTest (empNumb, DOBirth)
SELECT 30 ,'1985-12-13' UNION ALL
SELECT 25 ,'1980-11-18' UNION ALL
SELECT 21 ,'1978-01-19' UNION ALL
SELECT 7 ,'1985-12-13' UNION ALL
SELECT 5 ,'1975-07-23' 
GO
SELECT * FROM dbo.CCTest
GO

Here we can see our computed column:

To verify that the computed column will be updated for any updates, we will update [DOBirth] for [empNumb] 25.

Script # 3: Update DOBirth of empNumb 25

USE AdventureWorks
GO 
UPDATE CCtest
SET DOBirth = '1960-03-25'
WHERE empnumb = 25
GO
SELECT * FROM dbo.CCTest
WHERE Empnumb = 25
GO

Here we can see our computed column has been updated.

Persisted
You may have noticed that we also used the property "Persisted" for our computed column. This property for computed columns has been introduced in SQL Server 2005 and onwards. It is important for any computed column, because many additional features depend on it. To be able to make a computed column as Persisted it has to be deterministic.

Here are a few rules:

  • If Persisted property is off then calculated column will be just a virtual column. No data for this column will be stored on disk and values will be calculated every time when referenced in a script. If this property is set active then data of computed column will be stored on disk.
  • Any update in referenced column will be synchronized automatically in computed column if it is Persisted.
  • Along with some other conditions Persisted is required to create an index on the computed column.

Nullability
Nullibility for a computed column value will be determined by the database engine itself. The result of a non-nullable referenced column may be NULL in certain conditions to avoid possible overflows or underflows. You can provide an alternate value for NULL using the ISNULL(check_expression, constant), if required.

Some Limitations

  • For SQL Server 2000 you can not create a persisted computed column.
  • You can not reference columns from other tables for a computed column expression directly.
  • You can not apply insert or update statements on computed columns.
  • If you are combining operators of two different data types in your expression then operator of lower precedence will be converted to that of higher precedence. If implicit conversion is not possible then error will be generated.
  • A subquery can not be used as an expression for creating a computed column.
  • Computed columns can be used in SELECT lists, WHERE or ORDER BY clauses and as regular expressions , but to use a computed column as CHECK, FOREIGN KEY or NOT NULL constraints you have to set it to Persisted.
  • To use a computed column as Primary or Unique Key constraint it should be defined by a deterministic expression and data type of computed column expression should be indexable.

Next Steps

  • While planning for any computed column, please keep in mind that although a Persisted computed column will reduce overhead for calculations at run time it will consume more space on disk.
  • To get Nullability of any computed column in a table, use the COLUMNPROPERTY function with the AllowsNull property.
  • Creating indexes on computed columns requires certain conditions to be fulfilled. For details of these conditions please visit BOL


Related Tips: More | Become a paid author


Last Update: 2/6/2009

Share: Share 






Comments and Feedback:

Thursday, March 04, 2010 - 1:34:42 PM - dlsampson Read The Tip

Excellent Tip! Worked perfectly. Now, I need some help expanding on this. I have a table for Approvals in which I calculate expiration dates for the approval. What I want to do is calculate different expiration dates based upon approval type stored in a single column ApprovalType.

Conditional Approval expires after 1-year

Full Approval expires after 5-years.

Using the Computed Columns in SQL Server tip, how can I calculate dates based upon differing values?

 

Thanks in advance for your help with this.

David


Thursday, March 04, 2010 - 3:46:22 PM - dlsampson Read The Tip

 Wahoo! I figured it out!

You can use CASE functions within the Computed Columns. Here's what worked for me:

(case [ApprovalType] when (2) then dateadd(year,(5),[ApprovalDate]) else dateadd(year,(1),[ApprovalDate]) end)

So, now, all my Conditional Approvals have a 1-year expiry date and all my Full Approvals have a 5-year date.

David


Friday, March 05, 2010 - 12:15:07 AM - @tif Read The Tip

 Case statement as you used, is very suiatble for this task.

Thanks


Wednesday, February 01, 2012 - 3:02:49 PM - Chris Cody Read The Tip
One thing to be aware of, if your computed column derives its value from a function, and you want to change how the function works, you may have to rebuild your table containing the computed column. This means that you should really really like your function before you use it in a computed column.

Wednesday, February 01, 2012 - 11:52:44 PM - Atif Read The Tip

Chiris, Thanks for pointing out this important aspect. I would cover this process and associated concepts in a seperate article.


Wednesday, May 09, 2012 - 4:40:08 PM - Jim Read The Tip

I needed to add 


SET ANSI_NULLS, QUOTED_IDENTIFIER ON

for all my stored procs editing the table with a computed column... (not in the proc, rather during creation) to avoid errors like this:

  [UPDATE failed because the following SET options have incorrect settings: QUOTED_IDENTIFIER] 

SET ANSI_NULLS ON
go
SET QUOTED_IDENTIFIER ON
go
create proc dbo.proc_myproc

...



Post a Comment or Question

Keep it clean and stay on the subject or we may delete your comment.
Your email address is not published. Required fields are marked with an asterisk (*)

*Name   *Email   Notify for updates
Comments
*Enter Code refresh code


 
Sponsor Information
"Amazing, Amazing, Amazing! SQL doctor is truly one of the most powerful tools I have seen."

It takes just 5 minutes to connect your SQL Databases to source control. Got 5 minutes? Get started now.

Need SQL Server help and not sure where to turn? Reach out to the Edgewood experts for a Health Check starting at $995.

Free Trial: Get Proactive Insight with SpotlightŪ for SQL Server Enterprise.

Solving SQL Server problems for millions of DBAs and Devs since 2006. Join now.

Free Learning - Introduction to SQL Azure Delivered by Herve Roggero on Wednesday, June 13 @ 3:00 PM EST


Copyright (c) 2006-2012 Edgewood Solutions, LLC All rights reserved
privacy | disclaimer | copyright | advertise | about
authors | contribute | feedback | giveaways | user groups
Some names and products listed are the registered trademarks of their respective owners.


Edgewood Solutions LLC | MSSharePointTips.com | MSSQLTips.com