Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Obtenir les colonnes sous-jacentes d'une vue en fonction de son jeu de résultats

L'un des avantages des vues de base de données est qu'elles vous permettent d'exécuter des requêtes complexes sans avoir besoin de connaître le schéma de base de données sous-jacent.

Oui, il est vrai que vous devez connaître le schéma sous-jacent lorsque vous créez la vue, mais vous n'avez besoin de le faire qu'une seule fois. Une fois que vous l'avez créé, vous pouvez interroger cette vue toute la journée sans avoir à vous souvenir de tous les noms de table et de colonne, etc.

Les vues combinent généralement les données de plusieurs tables en une seule table virtuelle, ce qui en fait une sorte de "boîte noire". Tant que cela fonctionne comme prévu, vous n'avez pas à vous soucier des détails cachés.

Et si vous faites voulez-vous vérifier une vue pour ses tables et colonnes sous-jacentes ?

Alors que le sp_help La procédure stockée système vous fournira des informations sur les colonnes renvoyées par la vue, elle ne fournit pas d'informations sur les colonnes des tables de base référencées dans la vue.

Et oui, il existe de nombreuses façons de vérifier la définition réelle de la vue. Mais s'il s'agit d'une vue large, vous courez le risque de loucher, en essayant simplement de sélectionner toutes les tables de base réelles impliquées.

Cependant, il existe une autre méthode que vous pouvez utiliser pour renvoyer les tables de base et les colonnes utilisées par une vue.

Vous pouvez utiliser le sys.dm_exec_describe_first_result_set fonction de gestion dynamique du système pour renvoyer des métadonnées sur le jeu de résultats lorsque vous interrogez la vue.

La façon dont cela fonctionne est que vous transmettez une requête T-SQL à la fonction, et elle renverra des métadonnées sur le jeu de résultats. Dans ce cas, la requête que vous transmettez à la fonction serait la requête que vous utiliseriez pour interroger la vue.

L'un des avantages de l'utilisation de cette méthode est que vous obtenez les informations de la table de base et des colonnes dans une belle liste. Chaque colonne est répertoriée dans une ligne distincte.

En outre, vous pouvez affiner les résultats en affinant votre requête, ce qui signifie que vous pouvez éliminer toutes les colonnes non pertinentes (c'est-à-dire les colonnes qui sont dans la vue, mais qui ne sont pas pertinentes pour votre requête spécifique).

Exemple

Voici un exemple pour montrer comment cela fonctionne.

SELECT 
    CONCAT(
        source_server + '.', 
        source_database + '.', 
        source_schema + '.', 
        source_table + '.', 
        source_column) AS [Source Column],
    name AS [View Column],
    user_type_name,
    system_type_name,
    max_length,
    [precision],
    scale
FROM sys.dm_exec_describe_first_result_set(
    N'SELECT * FROM vAllCats', 
    NULL, 
    1
);

Résultat :

+-----------------------+---------------+------------------+--------------------+--------------+-------------+---------+
| Source Column         | View Column   | user_type_name   | system_type_name   | max_length   | precision   | scale   |
|-----------------------+---------------+------------------+--------------------+--------------+-------------+---------|
| Test.dbo.Cats.CatId   | CatId         | NULL             | int                | 4            | 10          | 0       |
| Test.dbo.Cats.CatName | CatName       | NULL             | varchar(60)        | 60           | 0           | 0       |
+-----------------------+---------------+------------------+--------------------+--------------+-------------+---------+

Ici, j'ai décidé d'utiliser le CONCAT() pour concaténer plusieurs noms de colonnes afin de faciliter la visualisation du schéma.

Dans ce cas, la colonne source et la colonne de vue » (c'est-à-dire la colonne renvoyée par la vue) partagent toutes deux le même nom. Cela se produira si la vue n'utilise pas d'alias pour la colonne.

Notez que la raison pour laquelle nous sommes en mesure d'obtenir les colonnes source, les tables, etc., est parce que nous utilisons 1 comme troisième argument. Lorsque nous utilisons cette valeur, chaque requête est analysée comme si elle avait un FOR BROWSE option sur la requête.

Lorsque la vue utilise des alias de colonne

Si la vue utilise des alias de colonne différents des noms de colonne sous-jacents réels, cela sera reflété dans nos résultats.

Dans cet exemple, nous interrogeons une vue qui utilise des alias de colonne.

SELECT 
    CONCAT(
        source_server + '.', 
        source_database + '.', 
        source_schema + '.', 
        source_table + '.', 
        source_column) AS [Source Column],
    name AS [View Column],
    user_type_name,
    system_type_name,
    max_length,
    [precision],
    scale
FROM sys.dm_exec_describe_first_result_set(
    N'SELECT * FROM vAlbums', 
    NULL, 
    1
);

Résultat :

+------------------------------------+---------------+------------------+--------------------+--------------+-------------+---------+
| Source Column                      | View Column   | user_type_name   | system_type_name   | max_length   | precision   | scale   |
|------------------------------------+---------------+------------------+--------------------+--------------+-------------+---------|
| Homer.Music.dbo.Artists.ArtistName | Artist        | NULL             | nvarchar(255)      | 510          | 0           | 0       |
| Homer.Music.dbo.Albums.AlbumName   | Album         | NULL             | nvarchar(255)      | 510          | 0           | 0       |
| Homer.Music.dbo.Genres.Genre       | Genre         | NULL             | nvarchar(50)       | 100          | 0           | 0       |
| Homer.Music.dbo.Artists.ArtistId   | ArtistId      | NULL             | int                | 4            | 10          | 0       |
| Homer.Music.dbo.Albums.AlbumId     | AlbumId       | NULL             | int                | 4            | 10          | 0       |
| Homer.Music.dbo.Genres.GenreId     | GenreId       | NULL             | int                | 4            | 10          | 0       |
+------------------------------------+---------------+------------------+--------------------+--------------+-------------+---------+

Si nous regardons les deux premières lignes, nous pouvons voir que les colonnes sous-jacentes (renvoyées par le source_column colonnes), sont différentes de la "View Column" (renvoyée par le name colonne).

Nous pouvons également voir que les colonnes source de cette vue sont situées sur un serveur lié appelé "Homer".

Une autre chose à noter est que lorsque vous utilisez le mode navigation comme nous sommes ici (c'est-à-dire avec 1 comme troisième argument), nous obtenons également d'autres colonnes impliquées dans l'exécution de la requête (ArtistId , AlbumId , et GenreId ), même s'ils ne sont pas réellement renvoyés dans le jeu de résultats.

Affiner la requête

Une des choses qui différencie sys.dm_exec_describe_first_result_set à partir de procédures comme sp_help et sp_helptext , c'est qu'il décrit l'ensemble de résultats pas la vue.

Les résultats que vous obtiendrez dépendront de la requête réelle que vous passerez, pas seulement de la vue.

Voici la même requête que dans l'exemple précédent, sauf que cette fois je sélectionne une seule colonne de la vue (au lieu d'utiliser le * caractère générique pour sélectionner toutes les colonnes).

SELECT 
    CONCAT(
        source_server + '.', 
        source_database + '.', 
        source_schema + '.', 
        source_table + '.', 
        source_column) AS [Source Column],
    name AS [View Column],
    user_type_name,
    system_type_name,
    max_length,
    [precision],
    scale
FROM sys.dm_exec_describe_first_result_set(
    N'SELECT Album FROM vAlbums', 
    NULL, 
    1
);

Résultat :

+----------------------------------+---------------+------------------+--------------------+--------------+-------------+---------+
| Source Column                    | View Column   | user_type_name   | system_type_name   | max_length   | precision   | scale   |
|----------------------------------+---------------+------------------+--------------------+--------------+-------------+---------|
| Homer.Music.dbo.Albums.AlbumName | Album         | NULL             | nvarchar(255)      | 510          | 0           | 0       |
| Homer.Music.dbo.Artists.ArtistId | ArtistId      | NULL             | int                | 4            | 10          | 0       |
| Homer.Music.dbo.Albums.AlbumId   | AlbumId       | NULL             | int                | 4            | 10          | 0       |
| Homer.Music.dbo.Genres.GenreId   | GenreId       | NULL             | int                | 4            | 10          | 0       |
+----------------------------------+---------------+------------------+--------------------+--------------+-------------+---------+

Donc cette fois, seules quatre lignes sont renvoyées au lieu de six.

Obtenir les colonnes sous-jacentes à partir de plusieurs vues

Comme mentionné, le sys.dm_exec_describe_first_result_set La fonction décrit l'ensemble des résultats, pas seulement une seule vue ou un autre objet.

Par conséquent, vous pouvez découvrir les colonnes sous-jacentes à partir de plusieurs vues et objets en une seule fois.

Exemple :

SELECT 
    CONCAT(
        source_server + '.', 
        source_database + '.', 
        source_schema + '.', 
        source_table + '.', 
        source_column) AS [Source Column],
    name AS [View Column],
    user_type_name,
    system_type_name,
    max_length,
    [precision],
    scale
FROM sys.dm_exec_describe_first_result_set(
    N'SELECT * FROM vAllCats c INNER JOIN vAllDogs d ON c.CatName = d.DogName', 
    NULL, 
    1
);

Résultat :

+-----------------------+---------------+------------------+--------------------+--------------+-------------+---------+
| Source Column         | View Column   | user_type_name   | system_type_name   | max_length   | precision   | scale   |
|-----------------------+---------------+------------------+--------------------+--------------+-------------+---------|
| Test.dbo.Cats.CatId   | CatId         | NULL             | int                | 4            | 10          | 0       |
| Test.dbo.Cats.CatName | CatName       | NULL             | varchar(60)        | 60           | 0           | 0       |
| Test.dbo.Dogs.DogId   | DogId         | NULL             | int                | 4            | 10          | 0       |
| Test.dbo.Dogs.DogName | DogName       | NULL             | nvarchar(255)      | 510          | 0           | 0       |
| Test.dbo.Dogs.GoodDog | GoodDog       | NULL             | bit                | 1            | 1           | 0       |
+-----------------------+---------------+------------------+--------------------+--------------+-------------+---------+