尝试将XML文件放入SQL Server表

时间:2019-02-26 00:31:16

标签: sql sql-server xml

我有一个很大的XML文件,我想进入SQL Server,所以我以可读格式查询它以供最终用户使用。我已经开始查询,我可以获取一些数据,但无法获取其余数据。

这是我的xml文件中的一组数据示例

<file>
  <edxMsg>
    <edxMsgHdr>
      <trnNm>ICSHDR2</trnNm>
      <trnAct>N</trnAct>
      <trnVer>01</trnVer>
      <rcvAgncy>PLA</rcvAgncy>
      <rcvAgncyObjId>555012069A</rcvAgncyObjId>
      <sndAgncy>CLK</sndAgncy>
      <sndAgncyApplnId>ICS</sndAgncyApplnId>
      <sentDate>20180920</sentDate>
      <sentTime>013113615000</sentTime>
      <sendGMTOffsetMin>-600</sendGMTOffsetMin>
      <sndMchnId>N</sndMchnId>
      <trnRefId>37</trnRefId>
    </edxMsgHdr>
    <trnData>
      <batchInfo>
        <numRecords>1151</numRecords>
      </batchInfo>
    </trnData>
  </edxMsg>
  <edxMsg>
    <edxMsgHdr>
      <trnNm>ICS400CUR</trnNm>
      <trnAct>N</trnAct>
      <trnVer>01</trnVer>
      <rcvAgncy>PLA</rcvAgncy>
      <rcvAgncyObjId>2015</rcvAgncyObjId>
      <sndAgncy>CLK</sndAgncy>
      <sndAgncyObjId>204630959S</sndAgncyObjId>
      <sndAgncyApplnId>ICS</sndAgncyApplnId>
      <sndUserId>PLAN-AAD192</sndUserId>
      <sentDate>20180919</sentDate>
      <sentTime>131812085000</sentTime>
      <sendGMTOffsetMin>-600</sendGMTOffsetMin>
      <sndMchnId>N</sndMchnId>
      <trnRefId>37</trnRefId>
    </edxMsgHdr>
    <trnData>
      <respCurrent>
        <freeText>2015</freeText>
        <rqstDate>20180919</rqstDate>
        <rqstBtch>5575</rqstBtch>
        <dob>19690328</dob>
        <surname>Knocksville</surname>
        <firstname>Jonny</firstname>
        <procDts>20180919131812057</procDts>
        <partner>N</partner>
        <tpId>555012069A</tpId>
        <numChild>1</numChild>
        <shCareDtl>
          <chId>1</chId>
          <shPercent>100</shPercent>
        </shCareDtl>
        <maxRateDtl>
          <maxRateBen>DSP</maxRateBen>
          <maxRateInd>Y</maxRateInd>
        </maxRateDtl>
        <maxRateDtl>
          <maxRateBen>FTB</maxRateBen>
          <maxRateInd>Y</maxRateInd>
        </maxRateDtl>
        <payDtl>
          <paySts>PYD</paySts>
          <payType>REG</payType>
          <ben>DSP</ben>
          <grntDate>20100817</grntDate>
          <payDate>20180914</payDate>
          <payFreq>2WE</payFreq>
          <payActAmt>90760</payActAmt>
          <cmpDtl>
            <cmp>BASIC</cmp>
            <cmpPayAmt>82620</cmpPayAmt>
            <cmpPayCode>ACT</cmpPayCode>
          </cmpDtl>
          <cmpDtl>
            <cmp>CES</cmp>
            <cmpPayAmt>1410</cmpPayAmt>
            <cmpPayCode>ACT</cmpPayCode>
          </cmpDtl>
          <cmpDtl>
            <cmp>PNSUP</cmp>
            <cmpPayAmt>6730</cmpPayAmt>
            <cmpPayCode>ACT</cmpPayCode>
          </cmpDtl>
        </payDtl>
        <payDtl>
          <paySts>PYD</paySts>
          <payType>REG</payType>
          <ben>FTB</ben>
          <grntDate>20000701</grntDate>
          <payDate>20180907</payDate>
          <payFreq>2WE</payFreq>
          <payLegAmt>51128</payLegAmt>
          <payActAmt>51128</payActAmt>
          <cmpDtl>
            <cmp>FTBA</cmp>
            <cmpPayAmt>23786</cmpPayAmt>
            <cmpPayCode>ACT</cmpPayCode>
          </cmpDtl>
          <cmpDtl>
            <cmp>FTBA</cmp>
            <cmpPayAmt>23786</cmpPayAmt>
            <cmpPayCode>LEG</cmpPayCode>
          </cmpDtl>
          <cmpDtl>
            <cmp>FTBB</cmp>
            <cmpPayAmt>10864</cmpPayAmt>
            <cmpPayCode>ACT</cmpPayCode>
          </cmpDtl>
          <cmpDtl>
            <cmp>FTBB</cmp>
            <cmpPayAmt>10864</cmpPayAmt>
            <cmpPayCode>LEG</cmpPayCode>
          </cmpDtl>
          <cmpDtl>
            <cmp>CESA</cmp>
            <cmpPayAmt>448</cmpPayAmt>
            <cmpPayCode>ACT</cmpPayCode>
          </cmpDtl>
          <cmpDtl>
            <cmp>CESA</cmp>
            <cmpPayAmt>448</cmpPayAmt>
            <cmpPayCode>LEG</cmpPayCode>
          </cmpDtl>
          <cmpDtl>
            <cmp>CESB</cmp>
            <cmpPayAmt>196</cmpPayAmt>
            <cmpPayCode>ACT</cmpPayCode>
          </cmpDtl>
          <cmpDtl>
            <cmp>CESB</cmp>
            <cmpPayAmt>196</cmpPayAmt>
            <cmpPayCode>LEG</cmpPayCode>
          </cmpDtl>
          <cmpDtl>
            <cmp>RA</cmp>
            <cmpPayAmt>15834</cmpPayAmt>
            <cmpPayCode>ACT</cmpPayCode>
          </cmpDtl>
          <cmpDtl>
            <cmp>RA</cmp>
            <cmpPayAmt>15834</cmpPayAmt>
            <cmpPayCode>LEG</cmpPayCode>
          </cmpDtl>
        </payDtl>
        <payDtl>
          <paySts>NXT</paySts>
          <payType>REG</payType>
          <ben>DSP</ben>
          <grntDate>20100817</grntDate>
          <payDate>20180928</payDate>
          <payFreq>2WE</payFreq>
          <payActAmt>91195</payActAmt>
          <cmpDtl>
            <cmp>BASIC</cmp>
            <cmpPayAmt>83030</cmpPayAmt>
            <cmpPayCode>ACT</cmpPayCode>
          </cmpDtl>
          <cmpDtl>
            <cmp>CES</cmp>
            <cmpPayAmt>1410</cmpPayAmt>
            <cmpPayCode>ACT</cmpPayCode>
          </cmpDtl>
          <cmpDtl>
            <cmp>PNSUP</cmp>
            <cmpPayAmt>6755</cmpPayAmt>
            <cmpPayCode>ACT</cmpPayCode>
          </cmpDtl>
        </payDtl>
        <payDtl>
          <paySts>NXT</paySts>
          <payType>REG</payType>
          <ben>FTB</ben>
          <grntDate>20000701</grntDate>
          <payDate>20180921</payDate>
          <payFreq>2WE</payFreq>
          <payLegAmt>51128</payLegAmt>
          <payActAmt>51128</payActAmt>
          <cmpDtl>
            <cmp>FTBA</cmp>
            <cmpPayAmt>23786</cmpPayAmt>
            <cmpPayCode>ACT</cmpPayCode>
          </cmpDtl>
          <cmpDtl>
            <cmp>FTBA</cmp>
            <cmpPayAmt>23786</cmpPayAmt>
            <cmpPayCode>LEG</cmpPayCode>
          </cmpDtl>
          <cmpDtl>
            <cmp>FTBB</cmp>
            <cmpPayAmt>10864</cmpPayAmt>
            <cmpPayCode>ACT</cmpPayCode>
          </cmpDtl>
          <cmpDtl>
            <cmp>FTBB</cmp>
            <cmpPayAmt>10864</cmpPayAmt>
            <cmpPayCode>LEG</cmpPayCode>
          </cmpDtl>
          <cmpDtl>
            <cmp>CESA</cmp>
            <cmpPayAmt>448</cmpPayAmt>
            <cmpPayCode>ACT</cmpPayCode>
          </cmpDtl>
          <cmpDtl>
            <cmp>CESA</cmp>
            <cmpPayAmt>448</cmpPayAmt>
            <cmpPayCode>LEG</cmpPayCode>
          </cmpDtl>
          <cmpDtl>
            <cmp>CESB</cmp>
            <cmpPayAmt>196</cmpPayAmt>
            <cmpPayCode>ACT</cmpPayCode>
          </cmpDtl>
          <cmpDtl>
            <cmp>CESB</cmp>
            <cmpPayAmt>196</cmpPayAmt>
            <cmpPayCode>LEG</cmpPayCode>
          </cmpDtl>
          <cmpDtl>
            <cmp>RA</cmp>
            <cmpPayAmt>15834</cmpPayAmt>
            <cmpPayCode>ACT</cmpPayCode>
          </cmpDtl>
          <cmpDtl>
            <cmp>RA</cmp>
            <cmpPayAmt>15834</cmpPayAmt>
            <cmpPayCode>LEG</cmpPayCode>
          </cmpDtl>
        </payDtl>
        <ddnDtl>
          <ddnBen>DSP</ddnBen>
          <ddnType>RCV</ddnType>
          <ddnAmt>9900</ddnAmt>
          <ddnDate>20180914</ddnDate>
        </ddnDtl>
        <ddnDtl>
          <ddnBen>DSP</ddnBen>
          <ddnType>DDF</ddnType>
          <ddnAmt>47319</ddnAmt>
          <ddnDate>20180914</ddnDate>
        </ddnDtl>
        <ddnDtl>
          <ddnBen>FTB</ddnBen>
          <ddnType>RCV</ddnType>
          <ddnAmt>6034</ddnAmt>
          <ddnDate>20180907</ddnDate>
        </ddnDtl>
        <ddnDtl>
          <ddnBen>FTB</ddnBen>
          <ddnType>DDF</ddnType>
          <ddnAmt>3000</ddnAmt>
          <ddnDate>20180907</ddnDate>
        </ddnDtl>
        <incDtl>
          <incType>FIN</incType>
          <incFreq>ANN</incFreq>
          <incAmt>525</incAmt>
          <incDate>20150320</incDate>
        </incDtl>
        <assDtl>
          <assType>CIS</assType>
          <assAmt>30000</assAmt>
          <assDate>20160920</assDate>
        </assDtl>
        <assDtl>
          <assType>HPE</assType>
          <assAmt>1000000</assAmt>
          <assDate>20100817</assDate>
        </assDtl>
      </respCurrent>
    </trnData>
  </edxMsg>
  </file>

这是我当前的代码

DECLARE @x xml

SELECT @x = P
FROM OPENROWSET (BULK 'C:\Temp\XML\CCesResponse.xml', SINGLE_BLOB) AS Tenants (P)

SELECT @x

DECLARE @hdoc int

EXEC sp_xml_preparedocument @hdoc OUTPUT, @x

SELECT *
FROM OPENXML (@hdoc, 'file/edxMsg/trnData/respCurrent', 2)
WITH 
    (dob varchar(100),
     firstname varchar(100),
     surname varchar(100),
     payDtl varchar(500)
    )

我正在尝试为以下每个栏目

file/edxMsg/trnData/respCurrent/payDtl/cmpDtl 

我已经尝试了所有我想的东西,但是我必须缺少一些东西。

任何指导都很好。

3 个答案:

答案 0 :(得分:1)

使用FROM OPENXML的方法(以及准备和删除XML文档的两个过程)已经过时,不应再使用(存在罕见的例外)。

请使用XML数据类型提供的native XML methods

尝试一下:

DECLARE  @xml XML=
N'place your XML here';

SELECT A.msg.value('(edxMsgHdr/trnNm)[1]','nvarchar(10)') AS trnNm
      ,A.msg.value('(edxMsgHdr/trnAct)[1]','nvarchar(10)') AS trnAct
      --Add all header values here
      ,A.msg.query('trnData') AS trnDataNode
FROM @xml.nodes('/file/edxMsg') A(msg);

中心思想是:

  • 使用.value()从XML内检索值
  • 使用CROSS APPLY YourXml.nodes('Some XPath')将重复元素转换为派生集。
  • 使用.query()检索XML的片段

在这种情况下,我使用了.nodes()来获得两行<edxMsg><edxMsgHdr>中的所有数据似乎都与1:1相关,因此我们可以使用.value()轻松选择它们。

困难的部分将是<trnData>的内容。

第一则消息仅显示简单的<batchInfo>,但第二则消息包含非常复杂的结构。

问题是:这似乎需要涵盖许多表上与1:n相关的复杂结构,因此需要大量思考。必须在派生列表中检索任何重复元素(例如<maxRateDtl><payDtl>。后者包含嵌套的重复元素本身(<cmpDtl>),甚至还有<ddnDtl><assDtl>

以下查询将帮助您从<payDtl>内获取一些数据:

SELECT A.msg.value('(edxMsgHdr/trnNm)[1]','nvarchar(10)') AS trnNm
      ,A.msg.value('(edxMsgHdr/trnAct)[1]','nvarchar(10)') AS trnAct
      ,A.msg.query('trnData') AS trnDataNode

      ,B.payDtl.value('(paySts)[1]','nvarchar(100)') AS paySts
      ,B.payDtl.value('(payType)[1]','nvarchar(100)') AS payType
      ,C.cmpDtl.value('(cmp)[1]','nvarchar(max)') AS cmp
      ,C.cmpDtl.value('(cmpPayAmt)[1]','decimal(10,4)') AS cmpPayAmt
FROM @xml.nodes('/file/edxMsg') A(msg)
CROSS APPLY A.msg.nodes('trnData/respCurrent/payDtl') B(payDtl)
CROSS APPLY B.payDtl.nodes('cmpDtl') C(cmpDtl)

此外,您必须非常了解edxMsg格式,如果您的消息中可能有此示例未涵盖的元素。

因此:我们可以提供并解释提取数据所需的工具,但是您必须了解自己,什么是可读格式 ...

答案 1 :(得分:0)

SQL Server提供XML数据类型以存储和搜索XML数据。如果要在SQL Server中搜索XML,可以执行以下步骤-

  1. 使用XML数据类型列创建表
  2. 在此表中插入XML
  3. 根据需要搜索XML节点

注意:如果您有大数据,则还应该在XML列上创建XML索引以提高搜索性能。

您可以在下面的链接中获得示例代码

How can I query a value in SQL Server XML column

答案 2 :(得分:0)

您应该真正检查内置的XQuery支持-并抛弃旧的OPENXML方法。

尝试执行以下操作以获取所有<cmpDtl>节点并从中提取详细信息:

SELECT
    Cmp = xc.value('(cmp)[1]', 'varchar(20)'),
    CmpPayAmount = xc.value('(cmpPayAmt)[1]', 'decimal(20,4)'),
    CmpPayCode = xc.value('(cmpPayCode)[1]', 'varchar(20)')
FROM
    @x.nodes('/file/edxMsg/trnData/respCurrent/payDtl/cmpDtl') AS XT(XC)

这将从XML中返回所有值的列表(三列CmpCmpPayAmountCmpPayCode),作为适当的关系数据,然后可以是例如插入表格中。