Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Ottieni le colonne sottostanti di una vista in base al suo set di risultati

Uno dei vantaggi delle viste del database è che consentono di eseguire query complesse senza dover conoscere lo schema del database sottostante.

Sì, è vero che devi conoscere lo schema sottostante quando crei la vista, ma devi farlo solo una volta. Dopo averlo creato, puoi eseguire query su quella vista tutto il giorno senza dover ricordare tutti i nomi di tabelle e colonne, ecc.

Le viste in genere combinano i dati di più tabelle in un'unica tabella virtuale, il che la rende una sorta di "scatola nera". Finché funziona come previsto, non devi preoccuparti dei dettagli nascosti.

Ma cosa succede se fai vuoi controllare una vista per le sue tabelle e colonne sottostanti?

Mentre il sp_help la procedura memorizzata di sistema fornirà informazioni sulle colonne restituite dalla vista, non fornisce informazioni sulle colonne nelle tabelle di base a cui si fa riferimento nella vista.

E sì, ci sono molti modi per verificare la definizione effettiva della vista. Ma se è una vista ampia, corri il rischio di strabico, cercando solo di selezionare tutte le tabelle di base effettive coinvolte.

Tuttavia, esiste un altro metodo che puoi utilizzare per restituire le tabelle e le colonne di base utilizzate da una vista.

Puoi usare il sys.dm_exec_describe_first_result_set funzione di gestione dinamica del sistema per restituire i metadati sul set di risultati quando si interroga la vista.

Il modo in cui funziona è passare una query T-SQL alla funzione e restituirà metadati sul set di risultati. In questo caso, la query che passi alla funzione sarebbe la query che useresti quando interroghi la vista.

Un vantaggio dell'utilizzo di questo metodo è che ottieni la tabella di base e le informazioni sulle colonne in un bell'elenco. Ogni colonna è elencata in una riga separata.

Inoltre, puoi restringere i risultati perfezionando la tua query, il che significa che puoi eliminare tutte le colonne irrilevanti (ovvero le colonne che sono nella vista, ma non sono rilevanti per la tua query specifica).

Esempio

Ecco un esempio per dimostrare come funziona.

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
);

Risultato:

+-----------------------+---------------+------------------+--------------------+--------------+-------------+---------+
| 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       |
+-----------------------+---------------+------------------+--------------------+--------------+-------------+---------+

Qui ho deciso di usare CONCAT() funzione per concatenare più nomi di colonna in modo da semplificare la visualizzazione dello schema.

In questo caso, la Colonna Sorgente e la Colonna Vista” (ovvero la colonna restituita dalla vista) condividono entrambe lo stesso nome. Ciò accadrà se la vista non utilizza un alias per la colonna.

Nota che il motivo per cui siamo in grado di ottenere le colonne, le tabelle, ecc. di origine è perché utilizziamo 1 come terzo argomento. Quando utilizziamo questo valore, ogni query viene analizzata come se avesse un FOR BROWSE opzione sulla query.

Quando la vista utilizza alias di colonna

Se la vista utilizza alias di colonna diversi dai nomi di colonna sottostanti effettivi, ciò si rifletterà nei nostri risultati.

In questo esempio, interroghiamo una vista che utilizza alias di colonna.

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
);

Risultato:

+------------------------------------+---------------+------------------+--------------------+--------------+-------------+---------+
| 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       |
+------------------------------------+---------------+------------------+--------------------+--------------+-------------+---------+

Se osserviamo le prime due righe, possiamo vedere che le colonne sottostanti (restituite da source_column colonne), sono diversi dalla "Colonna Visualizza" (restituita dal name colonna).

Possiamo anche vedere che le colonne di origine per questa vista si trovano su un server collegato chiamato "Homer".

Un'altra cosa da notare è che quando si utilizza la modalità di navigazione come siamo qui (cioè con 1 come terzo argomento), otteniamo anche altre colonne coinvolte nel completamento della query (ArtistId , AlbumId e GenreId ), anche se non vengono effettivamente restituiti nel set di risultati.

Perfeziona la query

Una delle cose che differenzia sys.dm_exec_describe_first_result_set da procedure come sp_help e sp_helptext , è che descrive il insieme di risultati non la vista.

I risultati che otterrai dipenderanno dalla query effettiva che passi, non solo dalla vista.

Ecco la stessa query dell'esempio precedente, tranne che questa volta seleziono solo una colonna dalla vista (invece di utilizzare il * carattere jolly per selezionare tutte le 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 Album FROM vAlbums', 
    NULL, 
    1
);

Risultato:

+----------------------------------+---------------+------------------+--------------------+--------------+-------------+---------+
| 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       |
+----------------------------------+---------------+------------------+--------------------+--------------+-------------+---------+

Quindi questa volta, vengono restituite solo quattro righe invece di sei.

Ottieni le colonne sottostanti da visualizzazioni multiple

Come accennato, il sys.dm_exec_describe_first_result_set La funzione descrive l'intero set di risultati, non solo una singola vista o un altro oggetto.

Pertanto, puoi scoprire le colonne sottostanti da più viste e oggetti tutto in una volta.

Esempio:

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
);

Risultato:

+-----------------------+---------------+------------------+--------------------+--------------+-------------+---------+
| 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       |
+-----------------------+---------------+------------------+--------------------+--------------+-------------+---------+