Declare @xml xml, @y int set @xml= '<ContactUpdates> <Contact VendorID="4"><LastName>McCrystle</LastName> <FirstName>Timothy</FirstName> </Contact> <Contact VendorID="10"> <LastName>Flynn</LastName> <FirstName>Erin</FirstName> </Contact></ContactUpdates>' Exec sp_xml_preparedocument @y output, @xml; Select * from openxml(@y,'/ContactUpdates/Contact') With (VendorID Varchar(20), LastName Varchar(30), FirstName Varchar(30))`
Je ne sais pas où l'erreur a été commise. S'il vous plaît aidez-moi avec cela.
Vous avez un mélange de projections axées sur les attributes et cinputs sur les éléments. La raison pour laquelle VendorId
est mappée, mais pas pour les deux éléments, est que l'atsortingbut censortingc est la valeur par défaut. Dans un scénario de hiérarchie mixte / complexe, comme xpath
ici , vous devrez fournir explicitement les mappages xpath
:
Exec sp_xml_preparedocument @y output, @xml; Select * from openxml(@y,'/ContactUpdates/Contact') With (VendorID Varchar(20) '@VendorID', -- Atsortingbute LastName Varchar(30) 'LastName', -- Element FirstName Varchar(30) 'FirstName'); -- Element
modifier
Quelque chose d'intéressant à noter est que l'atsortingbut flags
est, bien, un style bit [flag]. Cela signifie que vous pouvez OU les options set. 1
est centré sur l'atsortingbut, et 2
centré sur l'élément, donc 1 | 2 = 3
1 | 2 = 3
vous donnera les deux:
Exec sp_xml_preparedocument @y output, @xml; Select * from openxml(@y,'/ContactUpdates/Contact', 3) With (VendorID Varchar(20), LastName Varchar(30), FirstName Varchar(30)); -- Remember to release the handle with sp_xml_removedocument
Cependant, je ne crois pas que ce soit une bonne pratique – il ne transmet pas beaucoup au développeur, et il a probablement des implications de performances négatives étant donné qu'il est less spécifique que le xpath exact.
Utilisez le support XQuery natif approprié dans SQL Server:
SELECT VendorID = xc.value('@VendorID', 'int'), FirstName = xc.value('(FirstName)[1]', 'varchar(50)'), LastName = xc.value('(LastName)[1]', 'varchar(50)') FROM @xml.nodes('/ContactUpdates/Contact') AS XT(XC)
Vous donne facilement cette belle sortie:
Cela devrait vous aider
SELECT VendorID = Container.value('(@VendorID)[1]', 'varchar(50)'), LastName = Container.value('(LastName)[1]', 'varchar(50)'), FirstName = Container.value('(FirstName)[1]', 'varchar(50)') FROM (SELECT @xml Columndata) a CROSS APPLY Columndata.nodes('/ContactUpdates/Contact') AS T(Container)
Edité selon le commentaire de Stuart.
SELECT VendorID = Container.value('(@VendorID)[1]', 'varchar(50)'), LastName = Container.value('(LastName)[1]', 'varchar(50)'), FirstName = Container.value('(FirstName)[1]', 'varchar(50)') FROM @xml.nodes('/ContactUpdates/Contact') AS T(Container)