Estou tentando selecionar valores de uma tabela SQL como uma tabela XML com um formato específico.
Usando a tabela a seguir...
SELECT x.*
INTO #t
FROM (VALUES (1, 'John', 'Doe')) x(Id, FirstName, LastName)
SELECT *
FROM #t
DROP TABLE #t
Eu precisaria de uma saída XML parecida com esta...
<Table>
<Row>
<Column>Id</Column>
<Column>FirstName</Column>
<Column>LastName</Column>
</Row>
<Row>
<Column>1</Column>
<Column>John</Column>
<Column>Doe</Column>
</Row>
</Table>
Consegui obter uma saída correspondente a isso usando UNION e XML PATH...
SELECT t1.*
INTO #t
FROM (VALUES (1, 'John', 'Doe')) t1(Id, FirstName, LastName);
WITH t2(xmlTable) AS (
SELECT t3.Id 'Column'
,''
,t3.FirstName 'Column'
,''
,t3.LastName 'Column'
FROM (
SELECT *
FROM (VALUES ('Id', 'FirstName', 'LastName')) t4(Id, FirstName, LastName)
UNION ALL
SELECT CONVERT(varchar(15), #t.Id)
,CONVERT(varchar(15), #t.FirstName)
,CONVERT(varchar(15), #t.LastName)
FROM #t) t3
FOR XML PATH ('Row'), ROOT('Table'))
SELECT t2.xmlTable
FROM t2
DROP TABLE #t
Mas isso parece muito trabalhoso. Existe uma solução mais elegante para isso? Especificamente, posso fazer isso sem o UNION, talvez usando apenas XML PATH?
Tente a seguinte solução com base no XQuery nativo do SQL Server.
É genérico, independentemente de quantas colunas a tabela tenha.
Os nomes das colunas não são codificados em lugar nenhum.
Pontos notáveis:
SELECT
está compondo nos bastidores um XML bruto (veja abaixo)..query()
compõe a saída desejada "visualmente" usando expressões XQuery FLWOR./root/r[1]/*
está limitando o FLWOR a apenas uma iteração para recuperar nomes de colunas dinamicamente chamandolocal-name()
a função XQuery.SQL
XML bruto
Saída
Não, não é possível fazer isso em um único nível de consulta sem usar
UNION ALL
. O SQL Server espera que os valores dos nós sejam dados da tabela, não nomes de objetos ou colunas (que devem ser definidos estaticamente normalmente).Você pode usar a excelente resposta de @YitzakKabinsky, mas outra opção totalmente dinâmica é usar
FOR JSON
,OPENJSON
agregar e consultar novamente os dados.db<>violino