我正在使用SQL Server 2012,並試圖從包含數據的XML字符串中將數據插入到多個表中。問題和困惑源於包含多個節點的XML,因此它不僅僅是一次記錄。TSQL Query從xPath插入數據
由於這個原因,我使用輸出方法將數據與標識一起插入,以便我知道它插入的每條記錄的結果。
我的問題是由於XML字符串的結構,它沒有插入所有需要的數據。
下面是代碼,我用一個SQL小提琴一起工作的塊:
小提琴:http://sqlfiddle.com/#!6/d41d8/24236
DECLARE @xml xml = '<root>
<trainingEventID>572</trainingEventID>
<segment>
<segmentDate>03/03/2015</segmentDate>
<hours>4</hours>
<details>
<locale>653</locale>
<teammates>3</teammates>
<leaders>4</leaders>
</details>
<details>
<locale>655</locale>
<teammates>44</teammates>
<leaders>55</leaders>
</details>
<details>
<locale>657</locale>
<teammates>55</teammates>
<leaders>66</leaders>
</details>
<trainers>
<trainer>
<empID>User12341</empID>
</trainer>
</trainers>
</segment>
<segment>
<segmentDate>03/04/2015</segmentDate>
<hours>4</hours>
<details>
<locale>653</locale>
<teammates>3</teammates>
<leaders>4</leaders>
</details>
<details>
<locale>655</locale>
<teammates>44</teammates>
<leaders>55</leaders>
</details>
<details>
<locale>657</locale>
<teammates>55</teammates>
<leaders>66</leaders>
</details>
<trainers>
<trainer>
<empID>User1234</empID>
</trainer>
</trainers>
</segment>
<segment>
<segmentDate>03/13/2015</segmentDate>
<hours>4</hours>
<details>
<locale>653</locale>
<teammates>3</teammates>
<leaders>4</leaders>
</details>
<details>
<locale>655</locale>
<teammates>44</teammates>
<leaders>55</leaders>
</details>
<details>
<locale>657</locale>
<teammates>55</teammates>
<leaders>66</leaders>
</details>
<trainers>
<trainer>
<empID>User1234</empID>
</trainer>
</trainers>
</segment>
</root>'
-- Declare our temp tables
DECLARE @tmpSeg TABLE (teSegmentID INT, trainingEventID INT, segmentDate DATE, nonProdHrs int);
DECLARE @tmpEvents TABLE (teSegmentID INT IDENTITY(1,1), trainingEventID INT, segmentDate DATE, nonProdHrs INT);
-- First, Insert the main segments
INSERT INTO @tmpEvents(trainingEventID, segmentDate, nonProdHrs)
OUTPUT Inserted.teSegmentID, Inserted.trainingEventID, Inserted.segmentDate, Inserted.nonProdHrs INTO @tmpSeg
SELECT ParamValues.x1.value('../trainingEventID[1]', 'INT'),
ParamValues.x1.value('(segmentDate/text())[1]', 'DATE'),
ParamValues.x1.value('(hours/text())[1]', 'INT')
FROM @xml.nodes('/root/segment') AS ParamValues(x1);
SELECT * FROM @tmpSeg
-- Now, we join on our temp table and insert the Segment Details
SELECT s.teSegmentID,
ParamValues.x1.value('(details/locale/text())[1]', 'INT') AS localeID,
ParamValues.x1.value('(details/teammates/text())[1]', 'INT') AS teammates,
ParamValues.x1.value('(details/leaders/text())[1]', 'INT') AS leaders,
ParamValues.x1.value('(../trainingEventID/text())[1]', 'INT') AS eventID,
ParamValues.x1.value('(segmentDate/text())[1]', 'DATE') AS date,
ParamValues.x1.value('(hours/text())[1]', 'INT') AS hours
FROM @tmpSeg AS s
INNER JOIN @xml.nodes('/root/segment') AS ParamValues(x1)
ON s.trainingEventID = ParamValues.x1.value('(../trainingEventID/text())[1]', 'INT')
AND s.segmentDate = ParamValues.x1.value('(segmentDate/text())[1]', 'DATE')
AND s.nonProdHrs = ParamValues.x1.value('(hours/text())[1]', 'INT')
你可以從XML結構看,它被分解成幾部分。有一個segment
,然後在該段內可以有多個Details
節點。
查詢的第一步是創建所有看起來工作正常的段。每個段都被創建並且標識存儲在輸出的臨時表中。
接下來,我需要使用其父段的標識爲每個詳細信息節點創建記錄。我通過從輸出中加入一些臨時表來獲得所需的詳細信息。
此問題與多個details
節點有關,它只訪問第一個節點並存儲其數據。
使用此示例的最後一條語句中的輸出應該包含9條記錄。每個分段有3個details
節點,總共有3個分段。
不知道如何做到這一點,但它使我瘋狂。
感謝您的任何幫助。
除非我遺漏了一些東西,否則您會從返回的Xpath時間中選擇第一個值[1]。你期望得到什麼?[2]? – TheNorthWes 2015-03-02 16:44:01
在查詢的第二部分中,我只是選擇輸出並加入tmpTable,它只訪問第一個細節節點,其中每個節段總共有3個節點。這個問題來自於這段代碼,我相信'INNER JOIN @ xml.nodes('/ root/segment')AS ParamValues(x1)'作爲它在細分層級上的連接,然後查找細節。但是,它只能看到第一個細節節點,即使存在多個節點也是如此。 – SBB 2015-03-02 16:58:02
最終的結果應該是創建3個分段(目前正在這樣做),但是在一個單獨的表中,9個「細節」記錄在分段表中引用其父分段的標識。 – SBB 2015-03-02 17:05:44