Metadatos sin ejecución: domina sys.dm_exec_describe_first_result_set
En el desarrollo de soluciones de Business Intelligence, a menudo nos enfrentamos a la necesidad de conocer la estructura de salida de una consulta antes de que esta devuelva una sola fila. Ya sea porque estamos construyendo un motor de carga dinÔmico, generando archivos de exportación o mapeando esquemas en Microsoft Fabric, depender de la ejecución real para obtener metadatos es una estrategia ineficiente y, en ocasiones, arriesgada si manejamos volúmenes masivos de datos.
Históricamente, los desarrolladores de SQL Server recurrĆan a SET FMTONLY ON para obtener la cabecera de un conjunto de resultados. Sin embargo, este mĆ©todo estĆ” marcado como obsoleto (deprecated) y presenta comportamientos inconsistentes con consultas complejas. Desde SQL Server 2012, disponemos de la función de administración dinĆ”mica sys.dm_exec_describe_first_result_set, una herramienta mucho mĆ”s robusta que permite al motor de base de datos analizar la semĆ”ntica de la consulta y devolvernos un esquema completo sin tocar los datos.
En este artĆculo analizaremos cómo explotar esta función en entornos de consultorĆa reales, donde la precisión en el tipo de dato y la nulabilidad definen el Ć©xito de un modelo de datos. Si quieres pensar como el motor de SQL Server, entender cómo se resuelven los metadatos en tiempo de compilación es el primer paso.
¿Qué es sys.dm_exec_describe_first_result_set?
Es una Dynamic Management Function (DMF) que toma una cadena de texto con código T-SQL y devuelve una tabla con la descripción de las columnas del primer conjunto de resultados que generarĆa dicha consulta. Lo mĆ”s relevante es que no ejecuta el código; el motor realiza una resolución de nombres y tipos basĆ”ndose en el catĆ”logo del sistema.
Esta función es fundamental cuando trabajamos con herramientas que requieren una validación previa del esquema, como ocurre en la gestión proactiva de errores en Power Query o al definir estructuras de destino en un Data Lakehouse.
Sintaxis y parƔmetros bƔsicos
La función requiere tres parÔmetros principales:
- @tsql: La consulta o lote de comandos que queremos inspeccionar.
- @params: Definición de los parÔmetros si el código T-SQL es parametrizado (similar a sp_executesql).
- @browse_mode: Un entero (0, 1 o 2) que determina si se incluyen columnas ocultas o metadatos adicionales para el modo de exploración.
-- Ejemplo bÔsico de inspección de una consulta de Ventas
SELECT
column_ordinal,
name,
is_nullable,
system_type_name,
max_length,
precision,
scale
FROM sys.dm_exec_describe_first_result_set(
N'SELECT V.Fecha, V.Importe, P.Nombre AS Producto
FROM FactVentas V
INNER JOIN DimProducto P ON V.ProductoID = P.ProductoID',
NULL,
0
);Casos de uso en proyectos de BI y DWH
En mi experiencia como consultor, el uso de esta DMF no es solo una curiosidad técnica, sino una pieza clave en la automatización. Aquà presento tres escenarios donde aporta un valor diferencial:
1. Generación automÔtica de código (Code Generation)
Si estÔs construyendo una capa de staging y necesitas crear tablas que coincidan exactamente con la salida de una vista compleja, puedes usar esta función para iterar sobre los metadatos y construir un comando CREATE TABLE dinÔmico. Esto reduce errores humanos en la definición de longitudes de campos VARCHAR o precisiones de DECIMAL.
2. Validación de contratos en ETL
Antes de lanzar un proceso pesado de exportación de datos en SQL Server a archivos de texto, es vital confirmar que el origen no ha cambiado. Consultar esta DMF permite comparar el esquema actual con un esquema guardado en una tabla de control. Si una columna ha cambiado de nulable a no nulable, o si el tipo de dato ha variado, el proceso puede detenerse antes de corromper el destino.
3. AuditorĆa de linaje y tipos de datos
En sectores como el retail o la energĆa, donde las reglas de negocio cambian frecuentemente, es comĆŗn que las columnas calculadas en SQL pierdan precisión. Esta DMF nos permite monitorizar si una columna de Ā«ImporteĀ» ha sido degradada de MONEY a FLOAT debido a una transformación intermedia mal planteada, algo que afectarĆa directamente a la frescura y calidad de los datos en Microsoft Fabric.
El muro del SQL dinƔmico y las tablas temporales
No todo es perfecto. sys.dm_exec_describe_first_result_set tiene limitaciones severas cuando la consulta analizada no es determinista en su estructura. Si el motor no puede determinar la forma del resultado sin ejecutar el código, la función devolverĆ” un error o una fila con valores nulos en columnas crĆticas.
El problema de las tablas temporales (#)
Este es el escollo mÔs frecuente. Si tu script T-SQL crea una tabla temporal (#TempTable) y luego realiza un SELECT sobre ella, la DMF fallarÔ. ¿Por qué? Porque la tabla temporal no existe en el catÔlogo hasta que el código se ejecuta realmente. Como la DMF no ejecuta el código, el anÔlisis semÔntico se rompe al llegar a la referencia de la tabla inexistente.
Alternativa: Usa variables de tabla (@TableVariable). A diferencia de las tablas temporales, las variables de tabla forman parte de la declaración del lote y su estructura es conocida por el analizador en el momento de la inspección.
Ambigüedad en consultas condicionales
Si el script tiene una lógica de ramificación (IF... ELSE) que devuelve conjuntos de resultados con estructuras diferentes, la DMF intentarÔ analizar el primer camino posible. Si las estructuras difieren, SQL Server lanzarÔ un error indicando que no puede determinar un esquema único para el primer conjunto de resultados.
Comparativa de métodos de inspección
A continuación, comparamos las distintas formas de obtener metadatos en SQL Server para entender cuÔndo usar cada una:
| Método | ¿Requiere ejecución? | ¿Soporta tablas temporales? | Estado | Uso recomendado |
|---|---|---|---|---|
| SET FMTONLY ON | No | Limitado | Obsoleto | Legacy / No usar |
| sys.dm_exec_describe_first_result_set | No | No | Actual | Scripts dinÔmicos y automatización |
| sp_describe_first_result_set | No | No | Actual | Llamadas desde aplicaciones (Procedimiento) |
| SELECT TOP 0… INTO | SĆ (parcial) | SĆ | VĆ”lido | Creación rĆ”pida de tablas fĆsicas |
| sys.columns / sys.types | No | Solo objetos persistentes | Actual | Consultar tablas y vistas existentes |
Implementación avanzada: Manejo de errores y nulos
Cuando implementamos esta función en un entorno de producción, debemos envolverla en una lógica que gestione los casos en los que la consulta no es vÔlida. Si pasamos un código T-SQL con un error de sintaxis a la DMF, esta no lanzarÔ una excepción de SQL estÔndar, sino que devolverÔ un conjunto de resultados donde la columna error_number serÔ distinto de cero.
-- Inspección avanzada con detección de errores
DECLARE @sql_test NVARCHAR(MAX) = N'SELECT ID_Cliente, Suma_Ventas FROM FactVentas WHERE Anio = 2023';
SELECT
name AS nombre_columna,
system_type_name AS tipo_dato,
is_nullable AS es_nulable,
error_number,
error_message
FROM sys.dm_exec_describe_first_result_set(@sql_test, NULL, 0)
WHERE error_number IS NULL; -- Solo queremos resultados si el anÔlisis fue exitosoUn detalle técnico crucial: la columna is_nullable es extremadamente útil para optimizar modelos en Power BI. Si sabemos que una columna de clave externa en SQL es NOT NULL, podemos confiar en que la integridad referencial a nivel de base de datos es sólida, lo que nos permite tomar decisiones de diseño mÔs agresivas en el motor Vertipaq.
Errores frecuentes al usar la DMF
Tras aƱos viendo implementaciones en diversos clientes, estos son los errores mĆ”s comunes que deberĆas evitar:
- Asumir que analiza todo el script: La DMF solo describe el primer conjunto de resultados. Si tu script tiene tres
SELECT, los metadatos del segundo y tercero serÔn ignorados. - Ignorar el intercalado (Collation): La función devuelve información sobre la intercalación de las columnas de texto. Ignorar esto al generar tablas dinÔmicas puede provocar errores de «Collation mismatch» en procesos de
JOINposteriores. - Uso de cursores o código muy complejo: Aunque la función es potente, scripts con una lógica de control de flujo muy enrevesada pueden hacer que el analizador se rinda y devuelva un error de «metadata could not be determined».
- No escapar comillas: Al pasar el código T-SQL como una cadena
NVARCHAR, es vital escapar correctamente las comillas simples para evitar errores de sintaxis en el parƔmetro.
Checklist para el consultor de datos
- Verifica que la consulta no dependa de tablas temporales (
#). Si es asĆ, cĆ”mbialas a variables de tabla (@) para la inspección. - Comprueba siempre la columna
error_numberen la salida de la DMF antes de procesar los metadatos. - Utiliza el parƔmetro
@browse_mode = 1si necesitas identificar qué columnas son claves primarias o forman parte de la identidad de la tabla. - Asegúrate de que el usuario que ejecuta la DMF tiene permisos de
VIEW ANY DEFINITIONo permisos especĆficos sobre los objetos consultados. - Documenta el uso de esta función en tus procesos de ETL para que otros desarrolladores entiendan que el esquema se valida dinĆ”micamente.
Preguntas frecuentes
¿Es sys.dm_exec_describe_first_result_set mÔs lento que ejecutar la consulta?
No, es significativamente mÔs rÔpido. El motor solo realiza el anÔlisis sintÔctico y semÔntico (parsing y binding) sin generar un plan de ejecución completo ni acceder a las pÔginas de datos en disco. Es una operación de metadatos pura.
ĀæPuedo usarla para inspeccionar Procedimientos Almacenados?
SĆ, pero con cautela. Si el procedimiento almacenado utiliza SQL dinĆ”mico internamente o tablas temporales, la DMF no podrĆ” determinar los metadatos. En esos casos, es preferible usar sys.sp_describe_first_result_set con el nombre del procedimiento.
¿Qué diferencia hay entre esta DMF y sp_describe_first_result_set?
La funcionalidad principal es la misma. La diferencia es que sys.dm_exec_describe_first_result_set es una función de tabla que puedes usar en un SELECT (y por tanto unir con otras tablas), mientras que sp_describe_first_result_set es un procedimiento almacenado que devuelve un conjunto de resultados directamente a la aplicación.






