sql >> Base de Datos >  >> RDS >> Sqlserver

Obtener las columnas subyacentes de una vista en función de su conjunto de resultados

Una de las ventajas de las vistas de base de datos es que le permiten ejecutar consultas complejas sin necesidad de conocer el esquema de la base de datos subyacente.

Sí, es cierto que necesita conocer el esquema subyacente cuando crea la vista, pero solo necesita hacerlo una vez. Una vez que la haya creado, puede consultar esa vista durante todo el día sin necesidad de recordar todos los nombres de tablas y columnas, etc.

Las vistas suelen combinar datos de varias tablas en una sola tabla virtual, lo que la convierte en una especie de "caja negra". Mientras funcione según lo diseñado, no necesita preocuparse por los detalles ocultos.

Pero, ¿y si haces ¿Quiere comprobar una vista para sus tablas y columnas subyacentes?

Mientras que el sp_help El procedimiento almacenado del sistema le proporcionará información sobre las columnas devueltas por la vista, no proporciona información sobre las columnas en las tablas base a las que se hace referencia en la vista.

Y sí, hay muchas formas de comprobar la definición real de la vista. Pero si se trata de una vista grande, corre el riesgo de quedar bizco, simplemente tratando de seleccionar todas las tablas base reales involucradas.

Sin embargo, existe otro método que puede utilizar para devolver las tablas y columnas base utilizadas por una vista.

Puede usar el sys.dm_exec_describe_first_result_set función de gestión dinámica del sistema para devolver metadatos sobre el conjunto de resultados cuando consulta la vista.

La forma en que funciona es que pasa una consulta T-SQL a la función y devolverá metadatos sobre el conjunto de resultados. En este caso, la consulta que pasa a la función sería la consulta que usaría al consultar la vista.

Una ventaja de usar este método es que obtiene la tabla base y la información de la columna en una buena lista. Cada columna aparece en una fila separada.

Además, puede restringir los resultados refinando su consulta, lo que significa que puede eliminar cualquier columna irrelevante (es decir, columnas que están en la vista, pero que no son relevantes para su consulta específica).

Ejemplo

Aquí hay un ejemplo para demostrar cómo funciona.

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

Resultado:

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

Aquí, he decidido usar CONCAT() función para concatenar varios nombres de columna para facilitar la visualización del esquema.

En este caso, la columna de origen y la columna de vista (es decir, la columna devuelta por la vista) comparten el mismo nombre. Esto sucederá si la vista no usa un alias para la columna.

Tenga en cuenta que la razón por la que podemos obtener las columnas, tablas, etc. de origen es porque usamos 1 como tercer argumento. Cuando usamos este valor, cada consulta se analiza como si tuviera un FOR BROWSE opción en la consulta.

Cuando la vista usa alias de columna

Si la vista utiliza alias de columna que son diferentes a los nombres de columna subyacentes reales, eso se reflejará en nuestros resultados.

En este ejemplo, consultamos una vista que usa alias de columna.

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

Resultado:

+------------------------------------+---------------+------------------+--------------------+--------------+-------------+---------+
| 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 observamos las dos primeras filas, podemos ver que las columnas subyacentes (devueltas por source_column columnas), son diferentes a la "Columna de vista" (devuelta por el name columna).

También podemos ver que las columnas de origen de esta vista se encuentran en un servidor vinculado llamado "Homer".

Otra cosa a tener en cuenta es que cuando se usa el modo de navegación como si estuviéramos aquí (es decir, con 1 como tercer argumento), también obtenemos otras columnas que están involucradas en completar la consulta (ArtistId , AlbumId y GenreId ), aunque en realidad no se devuelven en el conjunto de resultados.

Refinar la consulta

Una de las cosas que diferencia a sys.dm_exec_describe_first_result_set de procedimientos como sp_help y sp_helptext , es que describe el conjunto de resultados no la vista.

Los resultados que obtenga dependerán de la consulta real que realice, no solo de la vista.

Esta es la misma consulta que en el ejemplo anterior, excepto que esta vez selecciono solo una columna de la vista (en lugar de usar el * comodín para seleccionar todas las columnas).

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

Resultado:

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

Entonces, esta vez, solo se devuelven cuatro filas en lugar de seis.

Obtenga las columnas subyacentes de varias vistas

Como se mencionó, el sys.dm_exec_describe_first_result_set La función describe todo el conjunto de resultados, no solo una sola vista u otro objeto.

Por lo tanto, puede descubrir las columnas subyacentes desde varias vistas y objetos de una sola vez.

Ejemplo:

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

Resultado:

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