我试图从XML文件中导入一大堆数据并且我无法添加相关密钥(存储在"密钥"节点中)以链接SQL服务器中的XML数据。
请考虑下面的XML代码段。
<person>
<keys>
<key>xx8546</key>
<key>yy369</key>
</keys>
<sex>f</sex>
<names>
<name>
<prename>Sarah</prename>
<surname>Connor</surname>
</name>
<name>
<prename>Sarah</prename>
<surname>Williams</surname>
</name>
</names>
<mmx>
<spouse-name>
<prename>John</prename>
<surname>Wyatt</surname>
</spouse-name>
<year-of-marriage>1985</year-of-marriage>
</mmx>
<pbx>
<spouse-name>
<prename>John</prename>
<surname>Williams</surname>
</spouse-name>
<child-name>
<prename>Sarah</prename>
<surname>Bean</surname>
</child-name>
<year-of-baptism>2007</year-of-baptism>
</pbx>
</person>
我需要将相关密钥添加到每个节点。
这是我的tsql的一部分:
DECLARE @x xml;
DECLARE @hdoc int;
SELECT @x = P
FROM OPENROWSET (BULK 'C:\person.xml', SINGLE_BLOB) AS Person(P)
EXEC sp_xml_preparedocument @hdoc OUTPUT, @x
--Person
SELECT * --into tbl_Person
FROM OPENXML (@hdoc, '/persons/person/names/name', 2)
WITH (
[key] nvarchar(100) '../../keys/key',
prename varchar(100),
surname varchar(100),
sex varchar(50) '../../sex'
)
以上代码仅将第一个键值插入两个结果中,例如<key xx8546 </key>
。请你能帮我解决这个令人沮丧的问题。
非常感谢,
BN。
答案 0 :(得分:1)
FROM OPENXML
与相应的SP准备和删除文档已过时,不应再使用。而是使用适当的methods the XML data type provides。
元素顺序是XML文档的固有部分。这不是最好的设计,但可以通过相对位置链接信息。如果这里缺少某些东西,显然你会遇到麻烦。
我不明白,<sex>
是如何关联的以及<mmx>
和<pbx>
在这里做了什么,但你可以走这条路:
DECLARE @xml XML=
N'<person>
<keys>
<key>xx8546</key>
<key>yy369</key>
</keys>
<sex>f</sex>
<names>
<name>
<prename>Sarah</prename>
<surname>Connor</surname>
</name>
<name>
<prename>Sarah</prename>
<surname>Williams</surname>
</name>
</names>
</person>';
查询以 inline-tally 开头。键的计数作为派生表返回。在这种情况下,Tally
将返回1
和2
的集。
现在,您可以使用此运行编号从XML中获取相关数据:
WITH Tally(Nr) AS (SELECT TOP (@xml.value(N'count(/person/keys/key)','int')) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values)
SELECT Nr
,@xml.value(N'(/person/keys/key[sql:column("Nr")]/text())[1]','nvarchar(max)') AS PersonKey
,@xml.value(N'(/person/names/name[sql:column("Nr")]/prename/text())[1]','nvarchar(max)') AS PersonPrename
,@xml.value(N'(/person/names/name[sql:column("Nr")]/surname/text())[1]','nvarchar(max)') AS PersonSurname
-- this will return the <sex> for both (as there is just one...)
,@xml.value(N'(/person/sex/text())[1]',N'nvarchar(max)') AS sex
FROM Tally;
结果
Nr PersonKey PersonPrename PersonSurname sex
1 xx8546 Sarah Connor f
2 yy369 Sarah Williams f