简体   繁体   English

将 XML 子节点插入 SQL 表

[英]Insert XML child node to SQL table

I've got an XML file like this and I'm working with SQL 2014 SP2我有一个这样的 XML 文件,我正在使用 SQL 2014 SP2

<?xml version='1.0' encoding='UTF-8'?>
<gwl>
<version>123456789</version>
<entities>
<entity id="1" version="123456789">
    <name>xxxxx</name>
    <listId>0</listId>
    <listCode>Oxxx</listCode>
    <entityType>08</entityType>
    <createdDate>03/03/1993</createdDate>
    <lastUpdateDate>05/06/2011</lastUpdateDate>
    <source>src</source>
    <OriginalSource>o_src</OriginalSource>
    <aliases>
       <alias category="STRONG" type="Alias">USCJSC</alias>
        <alias category="WEAK" type="Alias">'OSKOAO'</alias>
    </aliases>
    <programs>
        <program type="21">prog</program>
    </programs>
    <sdfs>
        <sdf name="OriginalID">9876</sdf>
    </sdfs>
    <addresses>
        <address>
            <address1>1141, SYA-KAYA STR.</address1>
            <country>RU</country>
            <postalCode>1234</postalCode>
        </address>
        <address>
            <address1>90, MARATA UL.</address1>
            <country>RU</country>
            <postalCode>1919</postalCode>
        </address>
    </addresses>
    <otherIds>
        <childId>737606</childId>
        <childId>737607</childId>
    </otherIds>
</entity>
</entities>
</gwl>

I made a script to insert data from the XML to a SQL table.我制作了一个脚本来将数据从 XML 插入到 SQL 表中。 How can I insert child node into a table?如何将子节点插入表中? I think I should replicate the row for each new child node but i don't know the best way to proceed.我想我应该为每个新的子节点复制该行,但我不知道继续的最佳方式。

Here is my SQL code这是我的 SQL 代码

   DECLARE @InputXML XML


   SELECT @InputXML = CAST(x AS XML)
   FROM OPENROWSET(BULK 'C:\MyFiles\sample.XML', SINGLE_BLOB) AS T(x)

    SELECT 
    product.value('(@id)[1]', 'NVARCHAR(10)') id, 
    product.value('(@version)[1]', 'NVARCHAR(14)')  ID
    product.value('(name[1])', 'NVARCHAR(255)') name,
    product.value('(listId[1])', 'NVARCHAR(9)')listId,
    product.value('(listCode[1])', 'NVARCHAR(10)')listCode,
    product.value('(entityType[1])', 'NVARCHAR(2)')entityType,
    product.value('(createdDate[1])', 'NVARCHAR(10)')createdDate,
    product.value('(lastUpdateDate[1])', 'NVARCHAR(10)')lastUpdateDate,
    product.value('(source[1])', 'NVARCHAR(15)')source,
    product.value('(OriginalSource[1])', 'NVARCHAR(50)')OriginalSource,
    product.value('(aliases[1])', 'NVARCHAR(50)')aliases,
    product.value('(programs[1])', 'NVARCHAR(50)')programs,
    product.value('(sdfs[1])', 'NVARCHAR(500)')sdfs,
    product.value('(addresses[1])', 'NVARCHAR(50)')addresses,
    product.value('(otherIDs[1])', 'NVARCHAR(50)')otherIDs

    FROM @InputXML.nodes('gwl/entities/entity') AS X(product)

You have a lot of different children here...你在这里有很多不同的孩子......

Just to show the principles:只是为了说明原则:

DECLARE @xml XML=
N'<gwl>
  <version>123456789</version>
  <entities>
    <entity id="1" version="123456789">
      <name>xxxxx</name>
      <listId>0</listId>
      <listCode>Oxxx</listCode>
      <entityType>08</entityType>
      <createdDate>03/03/1993</createdDate>
      <lastUpdateDate>05/06/2011</lastUpdateDate>
      <source>src</source>
      <OriginalSource>o_src</OriginalSource>
      <aliases>
        <alias category="STRONG" type="Alias">USCJSC</alias>
        <alias category="WEAK" type="Alias">''OSKOAO''</alias>
      </aliases>
      <programs>
        <program type="21">prog</program>
      </programs>
      <sdfs>
        <sdf name="OriginalID">9876</sdf>
      </sdfs>
      <addresses>
        <address>
          <address1>1141, SYA-KAYA STR.</address1>
          <country>RU</country>
          <postalCode>1234</postalCode>
        </address>
        <address>
          <address1>90, MARATA UL.</address1>
          <country>RU</country>
          <postalCode>1919</postalCode>
        </address>
      </addresses>
      <otherIds>
        <childId>737606</childId>
        <childId>737607</childId>
      </otherIds>
    </entity>
  </entities>
</gwl>'; 

-The query will fetch some values from several places. - 查询将从多个地方获取一些值。
--It should be easy to get the rest yourself... ——剩下的自己搞定应该很容易吧……

SELECT @xml.value('(/gwl/version/text())[1]','bigint') AS [version]
      ,A.ent.value('(name/text())[1]','nvarchar(max)') AS [Entity_Name]
      ,A.ent.value('(listId/text())[1]','int') AS Entity_ListId
      --more columns taken from A.ent
      ,B.als.value('@category','nvarchar(max)') AS Alias_Category
      ,B.als.value('text()[1]','nvarchar(max)') AS Alias_Content
      --similar for programs and sdfs
      ,E.addr.value('(address1/text())[1]','nvarchar(max)') AS Address_Address1
      ,E.addr.value('(country/text())[1]','nvarchar(max)') AS Address_Country
      --and so on
FROM @xml.nodes('/gwl/entities/entity') A(ent)
OUTER APPLY A.ent.nodes('aliases/alias') B(als)
OUTER APPLY A.ent.nodes('programs/program') C(prg)
OUTER APPLY A.ent.nodes('sdfs/sdf') D(sdfs)
OUTER APPLY A.ent.nodes('addresses/address') E(addr)
OUTER APPLY A.ent.nodes('otherIds/childId') F(ids);

The idea in short:简而言之这个想法:

  • We read non-repeating values (eg version ) from the xml variable directly我们直接从 xml 变量中读取非重复值(例如version
  • We use .nodes() to return repeating elements as derived sets.我们使用.nodes()将重复元素作为派生集返回。
  • We can use a cascade of .nodes() to dive deeper into repeating child elements by using a relativ Xpath (no / at the beginning).我们可以使用.nodes()级联通过使用相对 Xpath (在开头没有/ .nodes()来更深入地研究重复的子元素。

You have two approaches:你有两种方法:

  1. Read the XML like above into a staging table (simply by adding INTO #tmpTable before FROM ) and proceed from there (will need one SELECT ... GROUP BY for each type of child ).将上面的 XML 读入一个临时表(只需在FROM之前添加INTO #tmpTable )并从那里继续(对于每种类型的 child都需要一个SELECT ... GROUP BY )。
  2. Create one SELECT per type of child , using only one of the APPLY lines and shift the data into specific child tables.为每种类型的 child创建一个 SELECT,仅使用其中一个APPLY行并将数据转移到特定的子表中。

I would tend to the first one.我倾向于第一个。
This allows to do some cleaning, generate IDs, check for business rules, before you shift this into the target tables.这允许在将其转移到目标表之前进行一些清理、生成 ID、检查业务规则。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM