views:

114

answers:

3

SQL Server Beginner question:

I'm trying to introduce a computed column in SQL Server (2008). In the table designer of SQL Server Management Studio I can do this, but the designer only offers me one single edit cell to define the expression for this column. Since my computed column will be rather complicated (depending on several database fields and with some case differentiations) I'd like to have a more comfortable and maintainable way to enter the column definition (including line breaks for formatting and so on).

I've seen there is an option to define functions in SQL Server (scalar value or table value functions). Is it perhaps better to define such a function and use this function as the column specification? And what kind of function (scalar value, table value)?

To make a simplified example:

I have two database columns:

DateTime1 (smalldatetime, NULL)
DateTime2 (smalldatetime, NULL)

Now I want to define a computed column "Status" which can have four possible values. In Dummy language:

if (DateTime1 IS NULL and DateTime2 IS NULL)
    set Status = 0
else if (DateTime1 IS NULL and DateTime2 IS NOT NULL)
    set Status = 1
else if (DateTime1 IS NOT NULL and DateTime2 IS NULL)
    set Status = 2
else
    set Status = 3

Ideally I would like to have a function GetStatus() which can access the different column values of the table row which I want to compute the value of "Status" for, and then only define the computed column specification as GetStatus() without parameters.

Is that possible at all? Or what is the best way to work with "complicated" computed column definitions?

Thank you for tips in advance!

A: 

You can use a trigger to ensure a column value upon insert or update.

Pablo Santa Cruz
But a "trigger" is not a "computed column", isn't it? (Perhaps I should have written "SQL Server Beginner question" in bold.)
Slauma
No way - trigger and computed columns are two totally different concepts - a trigger won't help you here.
marc_s
+3  A: 

You can do this in an alter table statement:

alter table my_table_name
  add Status as 
    case 
      when (DateTime1 IS NULL and DateTime2 IS NULL) then 0
      when (DateTime1 IS NULL and DateTime2 IS NOT NULL) then 1
      when (DateTime1 IS NOT NULL and DateTime2 IS NULL) then 2
      else 3
    end

Edited to fix dumb copy-and-paste syntax error

Ray
Thanks, works fine! But what would I do when I want to change the formula later, let's say, to add an additional case? Do I need to delete the column "Status" from the table and run again such an "alter table" script?
Slauma
yes - you would have to drop it and re-create it
Ray
+1  A: 

You can always also use a user-defined function for this - wrap your "complicated" code into an UDF, and use that to define your computed column:

CREATE FUNCTION dbo.GetStatus(@DateTime1 DATETIME, @DateTime2 DATETIME)
RETURNS INT
AS BEGIN
    DECLARE @Result INT

    IF (@DateTime1 IS NULL AND @DateTime2 IS NULL)
       SET @Result = 0
    ELSE IF (@DateTime1 IS NULL AND @DateTime2 IS NOT NULL)
       SET @Result = 1
    ELSE IF (@DateTime1 IS NOT NULL AND @DateTime2 IS NULL)
       SET @Result = 2
    ELSE
       SET @Result = 3

    RETURN @Result
END

and then you define your computed column as:

ALTER TABLE dbo.YourTable
    ADD Status AS dbo.GetStatus(DateTime1, DateTime2)
marc_s
Thanks for reply! But I always need my database fields (which the computed column values depend on) as input parameters of a function, is that right? Isn't it possible to work in the function directly with the fields of a row (like members of an object)? For instance: instead using the parameter `@DateTime1` can I use something like `dbo.MyTable.DateTime1`?
Slauma
@Slauma: yes, you could read out the values for your rows inside the function - but you still need to pass in something to identify the column you're working on. Plus, if you're doing table access inside the function, you won't be able to make the resulting computed column **PERSISTED**, which is a desirable feature in certain cases
marc_s
@marc_s: In fact, the ability to make the computed column persisted is important for my purpose (need to have fast queries and an index for the column). I have started to follow Ray's proposal, but good to know for the future that user defined functions are possible as well to define a computed column.
Slauma