【问题标题】:How to generating IDs to preserve the relational integrity of multilevel XML while loading data using SSIS?如何在使用 SSIS 加载数据时生成 ID 以保持多级 XML 的关系完整性?
【发布时间】:2020-12-09 19:31:37
【问题描述】:

我正在尝试使用 SSIS 将 xml 文件加载到 sql server 数据库中。我的xml数据结构如下:

<PRODUCT xmlns="http://www.areabc.com/ABC" version="5.252">
  <APPLICANTS seller id="0">
    <APPLICANT first_name="ABC" last_name="DEF" middle_name="" xmlns:d3p1="http://www.areabc.com/InternalUse">
      <INFO state="" country="" />
      <ADDRESS duration="10" description="">
      </ADDRESS>
    </APPLICANT>
  </APPLICANTS>
  .
  .
  .
  
</PRODUCT>

每个 XML 文件大致给了我 20 个表(申请表、信息表、地址表等)((一些 XML 文件不包含所有节点))。我有 30 个要加载的 xml 文件。当我将数据转储到 SQL 服务器表中时,SSIS 自动生成表 ID,如申请人 ID 或 INFO_ID 等。现在这个申请人 ID 或 INFO_ID 是相同的,对于来自 30 个 XML 的所有 30 行的申请人 ID = 5 或 INFO_ID = 8文件。 20张桌子也是一样(图片)

.

我想知道如何为 SSIS 中的每个表生成唯一 ID,以便它们可以连接并保持关系完整性。示例:可以将申请人表与地址表连接起来。

感谢任何帮助

【问题讨论】:

    标签: sql-server xml ssis relational-database primary-key


    【解决方案1】:

    这是一个概念性的例子。

    您可以根据自己的需要进行调整。

    SQL

    -- DDL and sample data population, start
    USE tempdb;
    GO
    
    DROP TABLE IF EXISTS #city;
    DROP TABLE IF EXISTS #state;
    
    -- parent table
    CREATE TABLE #state  (
       stateID INT IDENTITY PRIMARY KEY, 
       stateName VARCHAR(30), 
       abbr CHAR(2), 
       capital VARCHAR(30)
    );
    -- child table (1-to-many)
    CREATE TABLE #city (
       cityID INT IDENTITY, 
       stateID INT NOT NULL FOREIGN KEY REFERENCES #state(stateID), 
       city VARCHAR(30), 
       [population] INT,
       PRIMARY KEY (cityID, stateID, city)
    );
    -- mapping table to preserve IDENTITY ids
    DECLARE @idmapping TABLE (GeneratedID INT PRIMARY KEY,
        NaturalID VARCHAR(20) NOT NULL UNIQUE);
    
    DECLARE @xml XML =
    N'<root>
       <state>
          <StateName>Florida</StateName>
          <Abbr>FL</Abbr>
          <Capital>Tallahassee</Capital>
          <cities>
             <city>
                <city>Miami</city>
                <population>470194</population>
             </city>
             <city>
                <city>Orlando</city>
                <population>285713</population>
             </city>
          </cities>
       </state>
       <state>
          <StateName>Texas</StateName>
          <Abbr>TX</Abbr>
          <Capital>Austin</Capital>
          <cities>
             <city>
                <city>Houston</city>
                <population>2100263</population>
             </city>
             <city>
                <city>Dallas</city>
                <population>5560892</population>
             </city>
          </cities>
       </state>
    </root>';
    -- DDL and sample data population, end
    
    ;WITH rs AS 
    (
        SELECT stateName   = p.value('(StateName/text())[1]', 'VARCHAR(30)'),
               abbr         = p.value('(Abbr/text())[1]', 'CHAR(2)'),
               capital      = p.value('(Capital/text())[1]', 'VARCHAR(30)')
        FROM   @xml.nodes('/root/state') AS t(p)
     )
     MERGE #state AS o
     USING rs ON 1 = 0
     WHEN NOT MATCHED THEN
        INSERT(stateName, abbr, capital)  
           VALUES(rs.stateName, rs.Abbr, rs.Capital)
     OUTPUT inserted.stateID, rs.stateName 
       INTO @idmapping (GeneratedID, NaturalID);
    
    ;WITH Details AS 
    (
        SELECT NaturalID   = p.value('(StateName/text())[1]', 'VARCHAR(30)'),
               city         = c.value('(city/text())[1]', 'VARCHAR(30)'),
               [population]   = c.value('(population/text())[1]', 'INT')
        FROM   @xml.nodes('/root/state') AS A(p)   -- parent
          CROSS APPLY A.p.nodes('cities/city') AS B(c) -- child
    ) 
    INSERT #city (stateID, city, [Population])
    SELECT m.GeneratedID, d.city, d.[Population]
    FROM   Details AS d
       INNER JOIN @idmapping AS m ON d.NaturalID = m.NaturalID;
    
    -- test
    SELECT * FROM #state;
    SELECT * FROM @idmapping;
    SELECT * FROM #city;
    

    【讨论】:

    • 不清楚你在问什么。恕我直言,无论 SSIS 生成什么 ID,它们都没有用,因为它们不是唯一的。
    • 像上面的例子一样,申请人表具有自动生成的申请人 ID (5)(父)。在子表(信息表)中有自动生成的 Info_id(8)。 Info 表也有申请人_Id (5)。我正在加载 30 个文件,它给了我 30 行具有相同申请人 ID(5)的文件。如果申请人 ID 随每个传入文件(如(1、2、3 等)而变化),那么这也将反映在子表中,并且可以轻松连接。我的问题是如何将此自动生成的 ID 更改为 SSIS 中的唯一 ID。谢谢。 @Yitzhak Khabinsky
    • "...我的问题是如何将此自动生成的 ID 更改为 SSIS 中的唯一 ID..." 我认为不可能。
    【解决方案2】:

    我也遇到了同样的问题!使用与上面相同的示例,我的数据如下所示:

    <PRODUCT xmlns="http://www.areabc.com/ABC" version="5.252">
      <APPLICANTS sequence id="0">
        <APPLICANT first_name="JANE" last_name="DOE">
          <INFO state="TX" />
          <ADDRESS duration="10" />
        </APPLICANT>
      </APPLICANTS>
      <APPLICANTS sequence id="2">
        <APPLICANT first_name="GARY" last_name="DOE">
          <INFO state="GA" />
          <ADDRESS duration="10" />
        </APPLICANT>
      </APPLICANTS>
      .
      .
    
    </PRODUCT>
    

    而当 SSIS 加载数据时,它会按如下方式加载:

    申请人表: 0 1

    申请表: 简·多伊 加里·多伊

    信息表: 德克萨斯州 遗传算法

    所以我无法知道 Jane 来自 TX。 SSIS 负载 分配随机 _ID,但申请人表上的 ID 与 Info 表上的 _ID 不匹配。

    【讨论】:

    • 欢迎来到 SO。这不是答案,请不要使用答案来添加此类评论。
    猜你喜欢
    • 1970-01-01
    • 2014-04-05
    • 1970-01-01
    • 2010-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-11
    • 1970-01-01
    相关资源
    最近更新 更多