Não sei se isso é mais rápido, mas você pode usar um truque:
FOR XML AUTO
irá omitir colunas sem conteúdo: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 é o resultado:
col3
está desaparecido... <tbl col1="1" col2="2" />
<tbl col1="1" />
<tbl />
Sabendo disso, você pode encontrar a lista de colunas, que não são NULL em todas as linhas, assim:
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
O conteúdo de
@ColList
agora é col1,col2
. Esta string você pode colocar em um SELECT
criado dinamicamente . ATUALIZAÇÃO:Dicas
Seria muito inteligente, substituir o
SELECT *
com uma lista de colunas criada a partir de INFORMATION_SCHEMA.COLUMNS
excluindo todos os não anuláveis . E - se necessário e possível - tipos, que contêm dados muito grandes (BLOBs). ATUALIZAÇÃO2:Desempenho
Não sei quais são seus dados muito grandes significa na verdade... Tentei isso em uma tabela com cerca de 500.000 linhas (com
SELECT *
) e retornou corretamente após menos de um minuto. Espero que seja rápido o suficiente...