Una limitación ampliamente conocida de las columnas calculadas en SQL Server es que no pueden acceder a los datos de otras tablas. Es decir, su expresión puede usar columnas en la misma tabla, pero no de otras tablas.
Pero esto es sólo una verdad a medias. Si bien no puede hacer referencia a la columna de otra tabla directamente dentro de su expresión, puede invocar una función definida por el usuario. Y, por lo tanto, podría crear una función definida por el usuario que realice el cálculo que necesita, luego simplemente llame a esa función como la expresión de su columna calculada.
Aquí hay un ejemplo para demostrarlo.
Tablas de muestra
Tengo una base de datos con las siguientes tablas:
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 | +-----------+------------------------+---------------+------------+-----------+
Estas tablas en realidad contienen más de 5 filas. He seleccionado las 5 filas superiores para que pueda obtener una imagen de los datos y la estructura de la tabla.
Ahora, imagina que quiero agregar una columna calculada a la primera tabla.
Quiero que la columna calculada proporcione la cantidad de álbumes de cada artista. En otras palabras, lo necesito para contar los álbumes en la otra tabla:Albums
mesa.
Dado que los datos están en otra tabla, no puedo hacer referencia a ellos directamente desde una columna calculada. Pero puedo crear una función definida por el usuario en su lugar y hacer referencia a esa función desde mi columna calculada.
Crear la función
Aquí hay una función simple que cuenta la cantidad de álbumes de un artista determinado:
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
Crear la columna calculada
Ahora que he creado la función, puedo agregar una columna calculada que haga referencia a ella.
ALTER TABLE Artists ADD AlbumCount AS dbo.ufn_AlbumCount(ArtistId);
Probar la columna calculada
Ahora puedo ejecutar una consulta contra los Artists
table para ver el resultado de mi columna calculada:
SELECT TOP(10) * FROM Artists;
Resultado:
+------------+------------------+--------------+-------------+--------------+ | 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 | +------------+------------------+--------------+-------------+--------------+
Indización
Solo puede usar la columna calculada en un índice si la función definida por el usuario que invoca tiene los siguientes valores de propiedad:
- EsDeterminista =verdadero
- IsSystemVerified =verdadero (a menos que la columna calculada se mantenga)
- Acceso a datos de usuario =falso
- Acceso a datos del sistema =falso