我正在使用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