Une limitation largement connue des colonnes calculées dans SQL Server est qu'elles ne peuvent pas accéder aux données d'autres tables. Autrement dit, votre expression peut utiliser des colonnes de la même table, mais pas d'autres tables.
Mais ce n'est qu'à moitié vrai. Bien que vous ne puissiez pas référencer la colonne d'une autre table directement dans votre expression, vous pouvez appeler une fonction définie par l'utilisateur. Et par conséquent, vous pouvez créer une fonction définie par l'utilisateur qui effectue le calcul dont vous avez besoin, puis simplement appeler cette fonction en tant qu'expression de votre colonne calculée.
Voici un exemple pour illustrer.
Tableaux d'exemple
J'ai une base de données avec les tables suivantes :
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 | +-----------+------------------------+---------------+------------+-----------+
Ces tables contiennent en fait plus de 5 lignes. J'ai sélectionné les 5 premières lignes afin que vous ayez une idée de la structure des données et de la table.
Maintenant, imaginez que je veuille ajouter une colonne calculée à la première table.
Je veux que la colonne calculée fournisse le nombre d'albums de chaque artiste. En d'autres termes, j'en ai besoin pour compter les albums dans l'autre tableau - les Albums
tableau.
Étant donné que les données se trouvent dans une autre table, je ne peux pas les référencer directement à partir d'une colonne calculée. Mais je peux créer une fonction définie par l'utilisateur à la place et référencer cette fonction à partir de ma colonne calculée.
Créer la fonction
Voici une fonction simple qui compte le nombre d'albums d'un artiste donné :
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
Créer la colonne calculée
Maintenant que j'ai créé la fonction, je peux ajouter une colonne calculée qui y fait référence.
ALTER TABLE Artists ADD AlbumCount AS dbo.ufn_AlbumCount(ArtistId);
Tester la colonne calculée
Maintenant, je peux exécuter une requête sur les Artists
table pour voir le résultat de ma colonne calculée :
SELECT TOP(10) * FROM Artists;
Résultat :
+------------+------------------+--------------+-------------+--------------+ | 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 | +------------+------------------+--------------+-------------+--------------+
Indexation
Vous ne pouvez utiliser la colonne calculée dans un index que si la fonction définie par l'utilisateur qu'elle appelle a les valeurs de propriété suivantes :
- Est déterministe =vrai
- IsSystemVerified =true (sauf si la colonne calculée est persistante)
- Accès aux données utilisateur =faux
- Accès aux données système =faux