【问题标题】:TSQL Inserting records from XML stringTSQL 从 XML 字符串插入记录
【发布时间】:2014-10-29 23:14:22
【问题描述】:

我有一个 SQL 查询,它将记录从我传递给它的 XML 字符串插入到表中。该字符串可以包含 1 个或多个节点,因此每个节点都是一条新记录。

这是我的 XML 字符串:

<root>
    <data>
      <segment>
         <trainingEventID>9</trainingEventID>
         <localeID>641</localeID>
         <numOfTeammates>12</numOfTeammates>
         <nonProdHrs>21</nonProdHrs>
         <segmentDate>10/10/2014</segmentDate>
         <trainers>
            <trainer>
               <empID>HUS123</empID>
            </trainer>
            <trainer>
               <empID>Dan123</empID>
            </trainer>
         </trainers>
      </segment>
   </data>
   <data>
      <segment>
         <trainingEventID>9</trainingEventID>
         <localeID>641</localeID>
         <numOfTeammates>12</numOfTeammates>
         <nonProdHrs>21</nonProdHrs>
         <segmentDate>10/25/2014</segmentDate>
         <trainers>
            <trainer>
               <empID>HUS123</empID>
            </trainer>
            <trainer>
               <empID>Dan123</empID>
            </trainer>
         </trainers>
      </segment>
   </data>
</root>

每个segment 都是一个新记录,添加到表中。

现在,我有一个名为trainers 的单独表。对于每个培训师,我还需要在该表中插入一条记录,但它需要有该段的last inserted record id

这是我的查询:

 INSERT INTO myTable(trainingEventID, localeID, segmentDate, numofTeammates, nonProdHrs)
    SELECT ParamValues.x1.value('trainingEventID[1]', 'INT'),
           ParamValues.x1.value('localeID[1]', 'INT'),
           ParamValues.x1.value('segmentDate[1]', 'DATE'),
           ParamValues.x1.value('numOfTeammates[1]', 'INT'),
           ParamValues.x1.value('nonProdHrs[1]', 'FLOAT')
    FROM   @xml.nodes('/root/data/segment') AS ParamValues(x1);

如何使用从细分插入创建的记录 ID 将培训师插入另一个表?

【问题讨论】:

  • 每个细分市场的关键是什么? trainingEventID + segmentDate?
  • 这似乎与我在此处提供的答案 (stackoverflow.com/questions/26124743/…) 几乎相同,除了“最后插入的段的记录 id”似乎很奇怪。您的意思是如果empID 值出现在多个Segment 中,您只需要最近的Segment(基于segmentDate)?或者你想要每个人 segmentDate 为那个 empID
  • 因此在上面的示例中,我们将有 2 个段节点(2 条记录)插入到表中。但是使用记录的自动增量 ID。现在,我需要将培训师添加到另一个表中,但他们需要引用刚刚插入的段。总共有 4 条记录插入到 trainer 表中,其中 2 条的段 id 为 1,另外 2 条的段 id 为 2。
  • 从这里,我可以说 select * from trainers where segmentId=1 它会告诉我两个教练

标签: sql-server xml tsql stored-procedures


【解决方案1】:

鉴于问题中此陈述的澄清:

对于每个培训师,我还需要在该表中插入一条记录,但它需要具有该段的最后插入记录 ID。

存在(在问题的 cmets 中找到):

总共有 4 条记录插入到 trainer 表中,其中 2 条的段 id 为 1,另外 2 条的段 id 为 2。

下面会将此数据插入到具有自动递增 ID 的相关表中。在示例数据中,我稍微改变了 EmpID 值,以更清楚地表明它确实按预期工作。

DECLARE @DocumentID INT, @ImportData XML;

SET @ImportData = N'
<root>
    <data>
      <segment>
         <trainingEventID>9</trainingEventID>
         <localeID>641</localeID>
         <numOfTeammates>12</numOfTeammates>
         <nonProdHrs>21</nonProdHrs>
         <segmentDate>10/10/2014</segmentDate>
         <trainers>
            <trainer>
               <empID>HUS123</empID>
            </trainer>
            <trainer>
               <empID>Dan123</empID>
            </trainer>
         </trainers>
      </segment>
    </data>
    <data>
      <segment>
         <trainingEventID>9</trainingEventID>
         <localeID>641</localeID>
         <numOfTeammates>12</numOfTeammates>
         <nonProdHrs>21</nonProdHrs>
         <segmentDate>10/25/2014</segmentDate>
         <trainers>
            <trainer>
               <empID>HUS1234</empID>
            </trainer>
            <trainer>
               <empID>Dan1234</empID>
            </trainer>
         </trainers>
      </segment>
   </data>
</root>';


DECLARE @Segment TABLE (SegmentId INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
                        TrainingEventID INT NOT NULL, -- Unique
                        LocaleID INT NOT NULL, -- Unique
                        NumOfTeammates INT,
                        NonProdHrs INT,
                        SegmentDate DATE); -- Unique
-- Ideally create UNIQUE INDEX with the 3 fields noted above
DECLARE @Trainer TABLE (TrainerId INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
                        SegmentID INT NOT NULL, -- FK to Segment.SegmentID
                        EmpID VARCHAR(50) NOT NULL);

EXEC sp_xml_preparedocument @DocumentID OUTPUT, @ImportData;

-- First pass: extract "Segment" rows
INSERT INTO @Segment
            (TrainingEventID, LocaleID, NumOfTeammates, NonProdHrs, SegmentDate)
   SELECT TrainingEventID, LocaleID, NumOfTeammates, NonProdHrs, SegmentDate
   FROM   OPENXML (@DocumentID, N'/root/data/segment', 2) 
             WITH (TrainingEventID   INT  './trainingEventID/text()', 
                   LocaleID          INT  './localeID/text()',
                   NumOfTeammates    INT  './numOfTeammates/text()',
                   NonProdHrs        INT  './nonProdHrs/text()',
                   SegmentDate       DATE './segmentDate/text()');


-- Second pass: extract "Trainer" rows
INSERT INTO @Trainer (SegmentID, EmpID)
   SELECT seg.SegmentID, trnr.EmpID
   FROM   OPENXML (@DocumentID, N'/root/data/segment/trainers/trainer', 2) 
             WITH (TrainingEventID   INT         '../../trainingEventID/text()',
                   LocaleID          INT         '../../localeID/text()',
                   SegmentDate       DATE        '../../segmentDate/text()',
                   EmpID             VARCHAR(50) './empID/text()') trnr
   INNER JOIN @Segment seg
           ON seg.[TrainingEventID] = trnr.[TrainingEventID]
          AND seg.[LocaleID] = trnr.[LocaleID]
          AND seg.[SegmentDate] = trnr.[SegmentDate];


EXEC sp_xml_removedocument @DocumentID;
-------------------

SELECT * FROM @Segment ORDER BY [SegmentID];
SELECT * FROM @Trainer ORDER BY [SegmentID];

输出:

SegmentId   TrainingEventID   LocaleID   NumOfTeammates   NonProdHrs   SegmentDate
1           9                 641        12               21           2014-10-10
2           9                 641        12               21           2014-10-25

TrainerId   SegmentID   EmpID
1           1           HUS123
2           1           Dan123
3           2           HUS1234
4           2           Dan1234

参考资料:

【讨论】:

  • 我正在尝试这个,但我收到错误 Procedure or function 'BS_Create_TrainingSegment' expects parameter '@DocumentID', which was not supplied. 我应该提供什么作为 @DocumentID
  • @SBB @DocumentID 不是输入参数。它在本地声明并填充为 EXEC sp_xml_preparedocument 上的 OUTPUT 参数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-30
  • 2017-05-06
  • 2015-03-27
  • 1970-01-01
相关资源
最近更新 更多