Sql server 在sql server 2012中读取具有动态行和属性的xml
我在下面输入了xmlSql server 在sql server 2012中读取具有动态行和属性的xml,sql-server,xml,Sql Server,Xml,我在下面输入了xml <root> <row1 invoice_number="WEDRT" vendor="Telekm" amount="233" status="1" created_date="42590" /> <row2 invoice_number="MSFDRT" vendor="ARS" amount="344" status="1" created_date="42955" /> </root> 我试过以下方
<root>
<row1 invoice_number="WEDRT" vendor="Telekm" amount="233" status="1" created_date="42590" />
<row2 invoice_number="MSFDRT" vendor="ARS" amount="344" status="1" created_date="42955" />
</root>
我试过以下方法
DECLARE
@xml XML,
@Columns VARCHAR(MAX)
SET @xml = '
<root>
<row1 invoice_number="WEDRT" vendor="Telekm" amount="233" status="1" created_date="42590" />
<row2 invoice_number="MSFDRT" vendor="ARS" amount="344" status="1" created_date="42955" />
</root>
'
BEGIN
SET NOCOUNT ON;
DECLARE @COUNT INT, @COUNTER INT, @TQUERY VARCHAR(2000), @SELECT VARCHAR(MAX), @VALUES VARCHAR(MAX)
SELECT * INTO #TEMPTABLE
FROM(
SELECT
CAST(x.v.query('local-name(.)') AS VARCHAR(100)) As AttributeName,
v.value('.' , 'VARCHAR(100)') AS Value
FROM @XML.nodes('//@*') x(v)
) A
SELECT * FROM #TEMPTABLE
DROP TABLE #TEMPTABLE
END
你在正确的轨道上。您需要做的唯一更改是选择所有元素而不是所有属性:
declare @x xml = '<root>
<row1 invoice_number="WEDRT" vendor="Telekm" amount="233" status="1" created_date="42590" />
<row2 invoice_number="MSFDRT" vendor="ARS" amount="344" status="1" created_date="42955" />
</root>';
select t.c.value('local-name(.)', 'sysname') as [NodeName],
t.c.value('./@invoice_number', 'varchar(50)') as [InvoiceNumber],
t.c.value('./@vendor', 'varchar(50)') as [Vender],
t.c.value('./@amount', 'money') as [Amount],
t.c.value('./@status', 'int') as [Status],
t.c.value('./@created_date', 'int') as [CreatedDate]
from @x.nodes('/root[1]/*') t(c);
我已经添加了节点名作为第一列,以防您需要它。如果没有,请将其从查询中删除。我已修改了您的查询,希望这有帮助
DECLARE @xml XML,
@Columns VARCHAR(MAX)
SET @xml = '
<root>
<row1 invoice_number="WEDRT" vendor="Telekm" amount="233" status="1" created_date="42590" />
<row2 invoice_number="MSFDRT" vendor="ARS" amount="344" status="1" created_date="42955" />
</root>
'
BEGIN
SET NOCOUNT ON;
DECLARE @COUNT INT, @COUNTER INT, @TQUERY VARCHAR(2000), @SELECT VARCHAR(MAX), @VALUES VARCHAR(MAX)
SELECT * INTO #TEMPTABLE
FROM(
SELECT CAST(x.v.query('local-name(.)') AS VARCHAR(100)) As AttributeName,
x.v.value('.' , 'VARCHAR(100)') AS [Value],
CAST(x.v.query('local-name(..)') AS VARCHAR(100)) As RowNumber
FROM @XML.nodes('//*//@*') x(v)
) A
DECLARE @t TABLE (AttributeName nvarchar(max), r int)
DECLARE @sql nvarchar(max),
@col nvarchar(max)
INSERT INTO @t
SELECT DISTINCT AttributeName,
ROW_NUMBER() OVER(PARTITION BY RowNumber ORDER BY RowNumber) as r
FROM #TEMPTABLE
SELECT @col = (
SELECT ','+QUOTENAME(AttributeName)
FROM @t
ORDER BY r
FOR XML PATH('')
)
SELECT @sql = N'
SELECT *
FROM #TEMPTABLE t
PIVOT (
MAX([Value]) FOR AttributeName IN ('+STUFF(@col,1,1,'')+')
) as pvt'
EXEC sp_executesql @sql
DROP TABLE #TEMPTABLE
END
主要思想是动态地调整结果。若要删除RowNumber列,可以使用“选择”+STUFF@col,1,1,+,而不是“选择*零件”您所说的读取是什么意思?你到底需要什么,以哪种形式?@RogerWolf:对不起,我刚刚更新了预期结果。你有一个很好的工作解决方案,你应该在输出中添加行号,或者在ech发票中添加一些标识,然后PIVOT@gofr1:旋转很好,但正如您所看到的,属性名称在5行之后重复出现。这就是为什么我想我不能透视。我添加了带有动态透视的解决方案,希望这有帮助。谢谢,但在运行时我不知道列的名称,所以我不能硬编码为发票号、供应商等。Beauty,这太棒了。谢谢。是否有可能从最后一个选择中删除rownumber?当然可以!我把这个加在我的答案上,看看它的结尾。我也这么做了。再次感谢。我必须使用临时表而不是表变量,因为xml字符串中的数据将是巨大的。
declare @x xml = '<root>
<row1 invoice_number="WEDRT" vendor="Telekm" amount="233" status="1" created_date="42590" />
<row2 invoice_number="MSFDRT" vendor="ARS" amount="344" status="1" created_date="42955" />
</root>';
select t.c.value('local-name(.)', 'sysname') as [NodeName],
t.c.value('./@invoice_number', 'varchar(50)') as [InvoiceNumber],
t.c.value('./@vendor', 'varchar(50)') as [Vender],
t.c.value('./@amount', 'money') as [Amount],
t.c.value('./@status', 'int') as [Status],
t.c.value('./@created_date', 'int') as [CreatedDate]
from @x.nodes('/root[1]/*') t(c);
DECLARE @xml XML,
@Columns VARCHAR(MAX)
SET @xml = '
<root>
<row1 invoice_number="WEDRT" vendor="Telekm" amount="233" status="1" created_date="42590" />
<row2 invoice_number="MSFDRT" vendor="ARS" amount="344" status="1" created_date="42955" />
</root>
'
BEGIN
SET NOCOUNT ON;
DECLARE @COUNT INT, @COUNTER INT, @TQUERY VARCHAR(2000), @SELECT VARCHAR(MAX), @VALUES VARCHAR(MAX)
SELECT * INTO #TEMPTABLE
FROM(
SELECT CAST(x.v.query('local-name(.)') AS VARCHAR(100)) As AttributeName,
x.v.value('.' , 'VARCHAR(100)') AS [Value],
CAST(x.v.query('local-name(..)') AS VARCHAR(100)) As RowNumber
FROM @XML.nodes('//*//@*') x(v)
) A
DECLARE @t TABLE (AttributeName nvarchar(max), r int)
DECLARE @sql nvarchar(max),
@col nvarchar(max)
INSERT INTO @t
SELECT DISTINCT AttributeName,
ROW_NUMBER() OVER(PARTITION BY RowNumber ORDER BY RowNumber) as r
FROM #TEMPTABLE
SELECT @col = (
SELECT ','+QUOTENAME(AttributeName)
FROM @t
ORDER BY r
FOR XML PATH('')
)
SELECT @sql = N'
SELECT *
FROM #TEMPTABLE t
PIVOT (
MAX([Value]) FOR AttributeName IN ('+STUFF(@col,1,1,'')+')
) as pvt'
EXEC sp_executesql @sql
DROP TABLE #TEMPTABLE
END
RowNumber invoice_number vendor amount status created_date
row1 WEDRT Telekm 233 1 42590
row2 MSFDRT ARS 344 1 42955