¿Alguna vez te has preguntado sobre el orden de ejecución de las expresiones SELECT en SQL Server? En la publicación de hoy, exploraremos una observación interesante sobre la ejecución secuencial de las expresiones SELECT en SQL Server.
Consideremos un escenario en el que necesitamos transformar datos JSON en un conjunto de resultados de tabla utilizando una serie de declaraciones SELECT y UNION ALL. Normalmente, usaríamos funciones como OPENJSON y PIVOT para lograr esta transformación. Sin embargo, en este caso particular, nuestros requisitos dictan que construyamos el código como una serie de declaraciones SELECT y UNION ALL.
El primer paso para construir nuestra consulta es analizar los datos JSON en filas y matrices de valores utilizando la función OPENJSON. Podemos lograr esto ejecutando la siguiente consulta:
SELECT *
FROM (
SELECT
filas.[key] AS NumeroFila,
filas.[value] AS ArrayFila
FROM
OPENJSON(N'{"data":[["a","b","c"],["d","e","f"]]}','$.data') filas
) r
CROSS APPLY OPENJSON(r.ArrayFila) v
ORDER BY
r.NumeroFila,
v.[key]
Esta consulta nos da un buen comienzo al analizar los datos JSON en filas y matrices de valores. Ahora, podemos proceder a construir nuestro código SQL dinámico para generar las declaraciones SELECT y UNION ALL.
A continuación, declaramos una variable llamada @ConsultaFila y comenzamos a construir nuestro código SQL dinámico. Usamos la función COALESCE para concatenar las expresiones SELECT para cada fila y columna:
DECLARE @ConsultaFila varchar(max)
SELECT TOP 134960239460263
@ConsultaFila = COALESCE(@ConsultaFila + ' ', '') + '''' + v.[value] + ''' as [Fila' + r.NumeroFila + 'Columna' + v.[key] + ']'
FROM (
SELECT
filas.[key] AS NumeroFila,
filas.[value] AS ArrayFila
FROM
OPENJSON(N'{"data":[["a","b","c"],["d","e","f"]]}','$.data') filas
) r
CROSS APPLY OPENJSON(r.ArrayFila) v
ORDER BY
r.NumeroFila,
v.[key]
PRINT 'SELECT ' + @ConsultaFila;
En este punto, tenemos el número correcto de filas y columnas. Sin embargo, todavía necesitamos agregar un UNION ALL SELECT antes del inicio de cada fila. Para lograr esto, podemos usar una variable llamada @FilaActual para realizar un seguimiento del número de fila actual. Si el número de fila cambia, insertamos el texto UNION ALL SELECT:
DECLARE @ConsultaFila varchar(max)
DECLARE @FilaActual int = 0
SELECT TOP 134960239460263
@ConsultaFila = COALESCE(@ConsultaFila + '', '') + IIF(r.NumeroFila > @FilaActual, CHAR(10) + 'UNION ALL' + CHAR(10) + 'SELECT ', ', ') + '''' + v.[value] + ''' as [Fila' + r.NumeroFila + 'Columna' + v.[key] + ']',
@FilaActual = IIF(r.NumeroFila > @FilaActual, r.NumeroFila, @FilaActual)
FROM (
SELECT
filas.[key] AS NumeroFila,
filas.[value] AS ArrayFila
FROM
OPENJSON(N'{"data":[["a","b","c"],["d","e","f"]]}','$.data') filas
) r
CROSS APPLY OPENJSON(r.ArrayFila) v
ORDER BY
r.NumeroFila,
v.[key]
PRINT STUFF(@ConsultaFila, 1, 1, 'SELECT');
Con esta lógica en su lugar, hemos construido con éxito nuestro código SQL dinámico para generar las declaraciones SELECT y UNION ALL deseadas.
Sin embargo, durante el proceso, hicimos una suposición sobre el orden de ejecución de SQL Server. Supusimos que SQL Server ejecuta las variables en la lista SELECT de manera secuencial. En nuestro caso, incrementamos la variable @FilaActual solo después de procesar la variable @ConsultaFila. Esta lógica funciona correctamente porque SQL Server ejecuta las expresiones de variables en el orden en que aparecen en la lista SELECT.
Vale la pena señalar que, en la mayoría de los casos, el orden de ejecución de las expresiones de columna en la instrucción SELECT no importa. Las columnas generalmente se ejecutan de forma independiente entre sí. Sin embargo, en nuestro ejemplo, el orden de ejecución de las columnas sí importa, y es tranquilizador ver que SQL Server ejecuta las expresiones en el orden secuencial esperado.
Aunque no podemos garantizar que este orden de ejecución siempre funcione, hemos intentado y no hemos logrado pensar en un escenario en el que SQL Server no procese las expresiones de la instrucción SELECT en el orden en que se enumeran. Hemos probado nuestra consulta extensivamente y parece funcionar como se esperaba en todos los casos.
Esperamos que hayas encontrado interesante esta observación sobre el orden de ejecución de las expresiones SELECT en SQL Server. No dudes en compartir tus pensamientos o cualquier escenario en el que hayas encontrado diferentes órdenes de ejecución en SQL Server.