2014-10-29 76 views
1

我有一個SQL查詢將記錄插入到我傳遞給它的XML字符串的表中。該字符串可以包含1個節點或多個節點,因此每個節點都是新記錄。TSQL從XML字符串插入記錄

這裏是我的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?

+0

每個細分市場的關鍵是什麼? 'trainingEventID' +'segmentDate'? – 2014-10-30 00:34:52

+0

這似乎幾乎與我在這裏提供的答案相同(http://stackoverflow.com/questions/26124743/bulk-insert-nested-xml-with-foreign-key-as-identity-column-of-first-table/ 26128718#26128718)除了「最後插入的段的記錄ID」似乎很奇怪。你的意思是說,如果'empID'值出現在多個段中,你只需要最近的段(基於'segmentDate')?或者你想爲每個單獨的'segmentDate'指定那個'empID'? – 2014-10-30 03:21:07

+0

所以在上面的例子中,我們將有2個段節點(2條記錄)插入到表中。但是用記錄的自動增量ID。現在,我需要將培訓師添加到另一個表中,但他們需要引用剛纔插入的片段。總共會有4條記錄插入教練表中,其中2條片段ID爲1,另外2條片段ID爲2。 – SBB 2014-10-30 12:33:57

回答

0

鑑於澄清的問題本聲明:

對於每一個教練,我還需要記錄插入該表,但它需要有該段的最後插入記錄的ID。

是(如在關於該問題的評論中找到):

會有一個總的4個記錄插入訓練者表,2具有1段id和其他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 

參考文獻:

+0

我試着這個,但我得到的錯誤'過程或函數'BS_Create_TrainingSegment'期望參數'@DocumentID',這沒有提供。 '我應該提供什麼作爲'@ DocumentID'? – SBB 2014-10-30 15:51:40

+0

@SBB「@ DocumentID」不是輸入參數。它在本地聲明並作爲'EXEC sp_xml_preparedocument'上的'OUTPUT'參數填充。 – 2014-10-30 15:56:59