XML导入SQL Server

时间:2017-03-27 18:26:31

标签: sql sql-server xml

这是我第一次使用XML文件。我已经能够将文件读入表格。现在我正在尝试访问数据元素以插入/更新到ERP中。

我使用https://docs.microsoft.com/en-us/sql/t-sql/functions/openxml-transact-sql作为指南而陷入困境。

我现在只尝试一次检索,试图保持简单: XML:

<TranscriptRequest xmlns="urn:org:pesc:message:TranscriptRequest:v1.0.0">
  <TransmissionData>
    <DocumentID xmlns="">88895-20170227180832302-ccd</DocumentID>
    <CreatedDateTime xmlns="">2017-02-27T18:08:32.303-08:00</CreatedDateTime>
    <DocumentTypeCode xmlns="">Request</DocumentTypeCode>
    <TransmissionType xmlns="">Original</TransmissionType>
    <Source xmlns="">
      <Organization>
        <DUNS>626927060</DUNS>
        <OrganizationName>AVOW</OrganizationName>
      </Organization>
    </Source>
    <Destination xmlns="">
      <Organization>
        <OPEID>3419</OPEID>
        <OrganizationName>Charleston Southern University</OrganizationName>
      </Organization>
    </Destination>
    <DocumentProcessCode xmlns="">PRODUCTION</DocumentProcessCode>
  </TransmissionData>
  <Request>
    <CreatedDateTime xmlns="">2017-02-27T00:00:00.000-08:00</CreatedDateTime>
    <Requestor xmlns="">
      <Person>
        <Birth>
          <BirthDate>1985-01-01</BirthDate>
        </Birth>
        <Name>
          <FirstName>Chad</FirstName>
          <LastName>test2</LastName>
        </Name>
        <AlternateName>
          <FirstName>Chad</FirstName>
          <LastName>Walker</LastName>
          <CompositeName>Walker, Chad</CompositeName>
        </AlternateName>
        <Contacts>
          <Address>
            <AddressLine>10260 west st</AddressLine>
            <City>Denver</City>
            <StateProvinceCode>CO</StateProvinceCode>
            <PostalCode>80236</PostalCode>
          </Address>
          <Phone>
            <CountryPrefixCode>1</CountryPrefixCode>
            <AreaCityCode>303</AreaCityCode>
            <PhoneNumber>8152848</PhoneNumber>
          </Phone>
          <Email>
            <EmailAddress>cwalker@parchment.com</EmailAddress>
          </Email>
        </Contacts>
      </Person>
    </Requestor>

我的SQL:

USE TMSEPRD

DECLARE @XML AS XML, @hDoc AS INT, @SQL NVARCHAR (MAX)

SELECT @XML = [XMLData] FROM [dbo].[CSU_Parchment_XMLwithOpenXML]

EXEC sp_xml_preparedocument @hDoc OUTPUT, @XML

SELECT BirthDate
FROM OPENXML(@hDoc, 'ROOT/Request/Requestor/Person/Birth/Birthdate')
WITH 
(
BirthDate varchar(20) '../@BirthDate'
)

EXEC sp_xml_removedocument @hDoc
GO

Birthdate仍为空白。到目前为止,我已尝试删除@Birthdate前的../,我已尝试删除@,我尝试从路径中删除Birthdate

2 个答案:

答案 0 :(得分:1)

使用Xml数据类型方法

DECLARE @XML XML='<TranscriptRequest xmlns="urn:org:pesc:message:TranscriptRequest:v1.0.0">
  <TransmissionData>
    <DocumentID xmlns="">88895-20170227180832302-ccd</DocumentID>
    <CreatedDateTime xmlns="">2017-02-27T18:08:32.303-08:00</CreatedDateTime>
    <DocumentTypeCode xmlns="">Request</DocumentTypeCode>
    <TransmissionType xmlns="">Original</TransmissionType>
    <Source xmlns="">
      <Organization>
        <DUNS>626927060</DUNS>
        <OrganizationName>AVOW</OrganizationName>
      </Organization>
    </Source>
    <Destination xmlns="">
      <Organization>
        <OPEID>3419</OPEID>
        <OrganizationName>Charleston Southern University</OrganizationName>
      </Organization>
    </Destination>
    <DocumentProcessCode xmlns="">PRODUCTION</DocumentProcessCode>
  </TransmissionData>
  <Request>
    <CreatedDateTime xmlns="">2017-02-27T00:00:00.000-08:00</CreatedDateTime>
    <Requestor xmlns="">
      <Person>
        <Birth>
          <BirthDate>1985-01-01</BirthDate>
        </Birth>
        <Name>
          <FirstName>Chad</FirstName>
          <LastName>test2</LastName>
        </Name>
        <AlternateName>
          <FirstName>Chad</FirstName>
          <LastName>Walker</LastName>
          <CompositeName>Walker, Chad</CompositeName>
        </AlternateName>
        <Contacts>
          <Address>
            <AddressLine>10260 west st</AddressLine>
            <City>Denver</City>
            <StateProvinceCode>CO</StateProvinceCode>
            <PostalCode>80236</PostalCode>
          </Address>
          <Phone>
            <CountryPrefixCode>1</CountryPrefixCode>
            <AreaCityCode>303</AreaCityCode>
            <PhoneNumber>8152848</PhoneNumber>
          </Phone>
          <Email>
            <EmailAddress>cwalker@parchment.com</EmailAddress>
          </Email>
        </Contacts>
      </Person>
    </Requestor>
  </Request>
</TranscriptRequest>';  

SQL查询:

with xmlnamespaces('urn:org:pesc:message:TranscriptRequest:v1.0.0' as ns)
  select t.n.value('BirthDate[1]','date')
  from @XML.nodes('ns:TranscriptRequest/ns:Request/Requestor/Person/Birth') t(n);

答案 1 :(得分:0)

命名空间

这个XML是如何生成的?这是你的控制吗?令我惊讶的是各种xmlns=""这是一遍又一遍地定义空的默认命名空间......尽管第一行中有一个默认的NS xmlns="urn:org:pesc:message:TranscriptRequest:v1.0.0",这似乎是正确的。

对于此命名空间问题,有许多解决方案:

  • 创建此项而不使用空xmlns - 如果这在您的控制之下
  • 在将此内容写入xml类型列/变量
  • 之前,使用REPLACE并删除xmlns=""(请注意前导空格!)
  • 使用通配符(*:)作为前两个级别的名称空间
  • 为默认值定义名称空间别名,并让空名称空间成为较低级别的默认名称

结构

您的XML似乎是普通的1:1,只有1个源,1个目标,1个请求。 <Request>内只有1个人,而<Person>以下只有1个姓名等等。有一个<Contacts>元素,听起来像1:n,但它似乎只包含一个地址,一个电话......阅读普通1:1很容易......

我将在.query()中使用带有两个调用的CTE,以便通过通配符轻松解决命名空间问题。这允许在没有命名空间的情况下读取其余内容:

如何阅读你的元素的一些例子,其余的由你决定......

WITH levels AS
(
    SELECT @xml.query(N'/*:TranscriptRequest/*:TransmissionData/*') AS td
          ,@xml.query(N'/*:TranscriptRequest/*:Request/*') AS rq
)
SELECT --TransmissionData
       td.value(N'(DocumentID/text())[1]',N'nvarchar(max)') AS DocumentID
      ,td.value(N'(CreatedDateTime/text())[1]',N'datetime') AS td_CreatedDateTime
      --more elemenst...
      ,td.value(N'(Source/Organization/DUNS/text())[1]',N'bigint') AS Source_Organization_DUNS
      --more elements...
      ,td.value(N'(Destination/Organization/OPEID/text())[1]',N'bigint') AS Destination_Organization_OPEID

      --Request
      ,rq.value(N'(CreatedDateTime/text())[1]',N'datetime') AS rq_CreatedDateTime
      --Request-Person
      ,rq.value(N'(Requestor/Person/Name/FirstName/text())[1]',N'nvarchar(max)') AS Requestor_FirstName

      --Contacts 
      ,rq.value(N'(Requestor/Person/Contacts/Address/AddressLine/text())[1]',N'nvarchar(max)') AS Requestor_AddressLine

FROM levels