No sé si esto es más rápido, pero podrías usar un truco:FOR XML AUTO
omitirá columnas sin contenido:
DECLARE @tbl TABLE(col1 INT,col2 INT,col3 INT);
INSERT INTO @tbl VALUES (1,2,NULL),(1,NULL,NULL),(NULL,NULL,NULL);
SELECT *
FROM @tbl AS tbl
FOR XML AUTO
Este es el resultado:col3
falta...
<tbl col1="1" col2="2" />
<tbl col1="1" />
<tbl />
Sabiendo esto, puede encontrar la lista de columnas, que no son NULL en todas las filas, así:
DECLARE @ColList VARCHAR(MAX)=
STUFF
(
(
SELECT DISTINCT ',' + Attr.value('local-name(.)','nvarchar(max)')
FROM
(
SELECT
(
SELECT *
FROM @tbl AS tbl
FOR XML AUTO,TYPE
) AS TheXML
) AS t
CROSS APPLY t.TheXML.nodes('/tbl/@*') AS A(Attr)
FOR XML PATH('')
),1,1,''
);
SELECT @ColList
El contenido de @ColList
ahora es col1,col2
. Esta cadena se puede colocar en un SELECT
creado dinámicamente .
ACTUALIZACIÓN:Sugerencias
Sería muy inteligente reemplazar el SELECT *
con una lista de columnas creada a partir de INFORMATION_SCHEMA.COLUMNS
excluyendo todos los no anulables . Y, si es necesario y posible, tipos que contienen datos muy grandes (BLOB).
ACTUALIZACIÓN 2:Rendimiento
No sé cuáles son sus datos muy grandes significa en realidad ... Acabo de probar esto en una tabla con alrededor de 500.000 filas (con SELECT *
) y volvió correctamente después de menos de un minuto. Espero que esto sea lo suficientemente rápido...