A widely known limitation of computed columns in SQL Server is that they can’t access data from other tables. That is, your expression can use columns in the same table, but not from other tables.
But this is only half-true. While you can’t reference another table’s column directly within your expression, you can invoke a user-defined function. And therefore, you could create a user-defined function that performs the calculation you need, then simply call that function as your computed column’s expression.
Here’s an example to demonstrate.
Sample Tables
I have a database with the following tables:
SELECT TOP(5) * FROM Artists; +------------+------------------+--------------+-------------+ | ArtistId | ArtistName | ActiveFrom | CountryId | |------------+------------------+--------------+-------------| | 1 | Iron Maiden | 1975-12-25 | 3 | | 2 | AC/DC | 1973-01-11 | 2 | | 3 | Allan Holdsworth | 1969-01-01 | 3 | | 4 | Buddy Rich | 1919-01-01 | 6 | | 5 | Devin Townsend | 1993-01-01 | 8 | +------------+------------------+--------------+-------------+ SELECT TOP(5) * FROM Albums; +-----------+------------------------+---------------+------------+-----------+ | AlbumId | AlbumName | ReleaseDate | ArtistId | GenreId | |-----------+------------------------+---------------+------------+-----------| | 1 | Powerslave | 1984-09-03 | 1 | 1 | | 2 | Powerage | 1978-05-05 | 2 | 1 | | 3 | Singing Down the Lane | 1956-01-01 | 6 | 3 | | 4 | Ziltoid the Omniscient | 2007-05-21 | 5 | 1 | | 5 | Casualties of Cool | 2014-05-14 | 5 | 1 | +-----------+------------------------+---------------+------------+-----------+
These tables actually contain more than 5 rows. I’ve selected the top 5 rows so that you get the picture of the data and table structure.
Now, imagine I want to add a computed column to the first table.
I want the computed column to provide the number of albums from each artist. In other words, I need it to count the albums in the other table – the Albums
table.
Seeing as the data is in another table, I can’t reference it directly from within a computed column. But I can create a user-defined function instead, and reference that function from within my computed column.
Create the Function
Here’s a simple function that counts the number of albums from a given artist:
CREATE FUNCTION [dbo].[ufn_AlbumCount] (@ArtistId int)
RETURNS smallint
AS
BEGIN
DECLARE @AlbumCount int;
SELECT @AlbumCount = COUNT(AlbumId)
FROM Albums
WHERE ArtistId = @ArtistId;
RETURN @AlbumCount;
END;
GO
Create the Computed Column
Now that I’ve created the function, I can add a computed column that references it.
ALTER TABLE Artists
ADD AlbumCount AS dbo.ufn_AlbumCount(ArtistId);
Test the Computed Column
Now I can run a query against the Artists
table to see the result of my computed column:
SELECT TOP(10) * FROM Artists;
Result:
+------------+------------------+--------------+-------------+--------------+ | ArtistId | ArtistName | ActiveFrom | CountryId | AlbumCount | |------------+------------------+--------------+-------------+--------------| | 1 | Iron Maiden | 1975-12-25 | 3 | 5 | | 2 | AC/DC | 1973-01-11 | 2 | 3 | | 3 | Allan Holdsworth | 1969-01-01 | 3 | 2 | | 4 | Buddy Rich | 1919-01-01 | 6 | 1 | | 5 | Devin Townsend | 1993-01-01 | 8 | 3 | | 6 | Jim Reeves | 1948-01-01 | 6 | 1 | | 7 | Tom Jones | 1963-01-01 | 4 | 3 | | 8 | Maroon 5 | 1994-01-01 | 6 | 0 | | 9 | The Script | 2001-01-01 | 5 | 1 | | 10 | Lit | 1988-06-26 | 6 | 0 | +------------+------------------+--------------+-------------+--------------+
Indexing
You can only use the computed column in an index if the user-defined function that it invokes has the following property values:
- IsDeterministic = true
- IsSystemVerified = true (unless the computed column is persisted)
- UserDataAccess = false
- SystemDataAccess = false