SQL将XML转换为表
在SQL2005中,有没有办法将以下xml转换为表SQL将XML转换为表,xml,sql-server-2005,tsql,xpath,xquery,Xml,Sql Server 2005,Tsql,Xpath,Xquery,在SQL2005中,有没有办法将以下xml转换为表 <root> <r> <data>"col1"</data> <data>"col2"</data> <data>"col3"</data> </r> <r> <data>"data1"</data> <data>""</data&g
<root>
<r>
<data>"col1"</data>
<data>"col2"</data>
<data>"col3"</data>
</r>
<r>
<data>"data1"</data>
<data>""</data>
<data>"data3"</data>
</r>
<r>
<data>"data"</data>
<data>"data"</data>
<data>"data"</data>
</r>
</root>
xml可以有不同数量的列,因此解决方案需要考虑这一点
提前谢谢。我从未做过,但我知道这是可以做到的 看一下本教程,它似乎非常接近您的要求。
列数不可变:SQL通常是固定列 但是,您可以在某种程度上预见到这一点
DECLARE @foo AS xml = '<root>
<r>
<data>"col1"</data>
<data>"col2"</data>
<data>"col3"</data>
</r>
<r>
<data>"data1"</data>
<data>""</data>
<data>"data3"</data>
</r>
<r>
<data>"data"</data>
<data>"data"</data>
<data>"data"</data>
</r>
</root>'
SELECT
REPLACE(x.item.value('(data)[1]', 'varchar(100)'), '"', '') AS col1,
REPLACE(x.item.value('(data)[2]', 'varchar(100)'), '"', '') AS col2,
REPLACE(x.item.value('(data)[3]', 'varchar(100)'), '"', '') AS col3,
REPLACE(x.item.value('(data)[4]', 'varchar(100)'), '"', '') AS col4,
REPLACE(x.item.value('(data)[5]', 'varchar(100)'), '"', '') AS col5,
REPLACE(x.item.value('(data)[6]', 'varchar(100)'), '"', '') AS col6,
REPLACE(x.item.value('(data)[7]', 'varchar(100)'), '"', '') AS col7,
REPLACE(x.item.value('(data)[8]', 'varchar(100)'), '"', '') AS col8,
REPLACE(x.item.value('(data)[9]', 'varchar(100)'), '"', '') AS col9,
REPLACE(x.item.value('(data)[10]', 'varchar(100)'), '"', '') AS col10
FROM
@foo.nodes('/root/r') x(item)
/root/r[1]确保获得第一行。row_number枚举在数字和列名之间建立连接的列
@SQL中的查询结果如下:
select
replace(r.r.value('data[1]', 'varchar(10)'), '"','') as [col1],
replace(r.r.value('data[2]', 'varchar(10)'), '"','') as [col2],
replace(r.r.value('data[3]', 'varchar(10)'), '"','') as [col3]
from @xml.nodes('/root/r[position()>1]') r(r)
/root/r[position>1]获取除第一个节点外的所有r节点。数据[1]中的1来自行号,[col1]来自相应的列名。quotename将括号[]添加到列别名中。如果没有quotename,此查询可用于SQL注入。替换用于从字符串中删除。它将删除所有出现的,因此,如果您希望成为某个值的一部分,则可以使用substring来删除
我使用varchar10作为列数据的大小。你应该根据需要修改它 这真是太棒了,正是我所需要的。谢谢@Mikael Eriksson的解释。谢谢@AllenG,但是我的数据已经作为nvarcharMax导入到一个表中,从我收集的数据来看,批量最适合从文件系统导入大型XML文件。
;WITH n(i) AS (SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9),
o(i) AS (SELECT n3.i * 100 + n2.i * 10 + n1.i FROM n n1, n n2, n n3)
SELECT
REPLACE(x.item.value('(data)[1]', 'varchar(100)'), '"', '') AS col1,
REPLACE(x.item.value('(data)[2]', 'varchar(100)'), '"', '') AS col2,
REPLACE(x.item.value('(data)[3]', 'varchar(100)'), '"', '') AS col3,
REPLACE(x.item.value('(data)[4]', 'varchar(100)'), '"', '') AS col4,
REPLACE(x.item.value('(data)[5]', 'varchar(100)'), '"', '') AS col5,
REPLACE(x.item.value('(data)[6]', 'varchar(100)'), '"', '') AS col6,
REPLACE(x.item.value('(data)[7]', 'varchar(100)'), '"', '') AS col7,
REPLACE(x.item.value('(data)[8]', 'varchar(100)'), '"', '') AS col8,
REPLACE(x.item.value('(data)[9]', 'varchar(100)'), '"', '') AS col9,
REPLACE(x.item.value('(data)[10]', 'varchar(100)'), '"', '') AS col10,
o.i
FROM
o
CROSS APPLY
@foo.nodes('/root/r[sql:column("o.i")]') x(item)
declare @xml xml
set @xml =
'<root>
<r>
<data>"col1"</data>
<data>"col2"</data>
<data>"col3"</data>
</r>
<r>
<data>"data1"</data>
<data>""</data>
<data>"data3"</data>
</r>
<r>
<data>"data"</data>
<data>"data"</data>
<data>"data"</data>
</r>
</root>'
declare @SQL nvarchar(max)
set @SQL = ''
select @SQL = @SQL + ',replace(r.r.value(''data['+
cast(T.rn as nvarchar(10))+
']'', ''varchar(10)''), ''"'','''') as '+
quotename(replace(T.ColName, '"', ''))
from
(
select
r.r.value('.', 'sysname') as ColName,
row_number() over(order by (select 1)) as rn
from @xml.nodes('/root/r[1]/data') r(r)
) as T
set @SQL = 'select '+stuff(@SQL, 1, 1, '')+
' from @x.nodes(''/root/r[position()>1]'') r(r)'
exec sp_executesql @SQL, N'@x xml', @x = @xml
select
r.r.value('.', 'varchar(10)') as ColName,
row_number() over(order by (select 1)) as rn
from @xml.nodes('/root/r[1]/data') r(r)
select
replace(r.r.value('data[1]', 'varchar(10)'), '"','') as [col1],
replace(r.r.value('data[2]', 'varchar(10)'), '"','') as [col2],
replace(r.r.value('data[3]', 'varchar(10)'), '"','') as [col3]
from @xml.nodes('/root/r[position()>1]') r(r)