2011-03-09 184 views
5

更新,以提供澄清当查询在SQL Server 2005中的XML,文档的多个标签在同一行中

这是我“遇到的麻烦米XML文件中的完整副本。

<Grower_Run xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Puller xsi:type="Puller"> 
    <Puller_Number xsi:type="xsd:int">16</Puller_Number> 
    </Puller> 
    <Run_ID xsi:type="xsd:string">SA1611030B</Run_ID> 
    <Crucible xsi:type="Crucible"> 
    <Crucible_Type xsi:type="xsd:string">RWNTYPE</Crucible_Type> 
    <Section> 
     <Grower_Run_Section> 
     <SectionID xsi:type="xsd:string">SA1611030B1</SectionID> 
     <Crystal_Growth> 
      <Growth_StartTime xsi:type="xsd:dateTime">2011-03-01T12:59:30</Growth_StartTime> 
      <Growth_Process> 
      <Growth_Process> 
       <Process_Name xsi:type="xsd:string">BODY</Process_Name> 
       <Single_Moment_Snapshot> 
       <Single_Moment_Snapshot> 
        <Snapshot_Name xsi:type="xsd:string">Body Start</Snapshot_Name> 
        <Snapshot_Datetime xsi:type="xsd:dateTime">2011-03-01T17:11:30</Snapshot_Datetime> 
        <Ingot_Length xsi:type="xsd:decimal">228.19</Ingot_Length> 
        <Heater_Temp xsi:type="xsd:decimal">1337.09</Heater_Temp> 
        <LS_Temp xsi:type="xsd:decimal">1243.00</LS_Temp> 
        <Heater_Power xsi:type="xsd:decimal">56.10</Heater_Power> 
       </Single_Moment_Snapshot> 
       <Single_Moment_Snapshot> 
        <Snapshot_Name xsi:type="xsd:string">Mid Body</Snapshot_Name> 
        <Snapshot_Datetime xsi:type="xsd:dateTime">2011-03-01T17:11:30</Snapshot_Datetime> 
        <Ingot_Length xsi:type="xsd:decimal">228.19</Ingot_Length> 
        <Heater_Temp xsi:type="xsd:decimal">1337.09</Heater_Temp> 
        <LS_Temp xsi:type="xsd:decimal">1243.00</LS_Temp> 
        <Heater_Power xsi:type="xsd:decimal">56.10</Heater_Power> 
       </Single_Moment_Snapshot> 
       <Single_Moment_Snapshot> 
        <Snapshot_Name xsi:type="xsd:string">Tail Start</Snapshot_Name> 
        <Snapshot_Datetime xsi:type="xsd:dateTime">2011-03-02T01:34:24</Snapshot_Datetime> 
        <Ingot_Length xsi:type="xsd:decimal">230.40</Ingot_Length> 
        <Heater_Temp xsi:type="xsd:decimal">1338.20</Heater_Temp> 
        <LS_Temp xsi:type="xsd:decimal">1243.40</LS_Temp> 
        <Heater_Power xsi:type="xsd:decimal">56.39</Heater_Power> 
       </Single_Moment_Snapshot> 
       </Single_Moment_Snapshot> 
      </Growth_Process> 
      </Growth_Process> 
      <Growth_FinishTime xsi:type="xsd:dateTime">2011-03-02T01:35:24</Growth_FinishTime> 
     </Crystal_Growth> 
     </Grower_Run_Section> 
     <Grower_Run_Section> 
     <SectionID xsi:type="xsd:string">SA1611030B9</SectionID> 
     <Crystal_Growth> 
      <Growth_StartTime xsi:type="xsd:dateTime">2011-03-02T04:02:37</Growth_StartTime> 
      <Growth_Process> 
      <Growth_Process> 
       <Process_Name xsi:type="xsd:string">BODY</Process_Name> 
       <Single_Moment_Snapshot> 
       <Single_Moment_Snapshot> 
        <Snapshot_Name xsi:type="xsd:string">Body Start</Snapshot_Name> 
        <Snapshot_Datetime xsi:type="xsd:dateTime">2011-03-02T07:54:39</Snapshot_Datetime> 
        <Ingot_Length xsi:type="xsd:decimal">231.80</Ingot_Length> 
        <Heater_Temp xsi:type="xsd:decimal">1340.00</Heater_Temp> 
        <LS_Temp xsi:type="xsd:decimal">1246.70</LS_Temp> 
        <Heater_Power xsi:type="xsd:decimal">56.60</Heater_Power> 
       </Single_Moment_Snapshot> 
       <Single_Moment_Snapshot> 
        <Snapshot_Name xsi:type="xsd:string">Mid Body</Snapshot_Name> 
        <Snapshot_Datetime xsi:type="xsd:dateTime">2011-03-02T07:54:39</Snapshot_Datetime> 
        <Ingot_Length xsi:type="xsd:decimal">231.80</Ingot_Length> 
        <Heater_Temp xsi:type="xsd:decimal">1340.00</Heater_Temp> 
        <LS_Temp xsi:type="xsd:decimal">1246.70</LS_Temp> 
        <Heater_Power xsi:type="xsd:decimal">56.60</Heater_Power> 
       </Single_Moment_Snapshot> 
       <Single_Moment_Snapshot> 
        <Snapshot_Name xsi:type="xsd:string">Tail Start</Snapshot_Name> 
        <Snapshot_Datetime xsi:type="xsd:dateTime">2011-03-03T06:47:19</Snapshot_Datetime> 
        <Ingot_Length xsi:type="xsd:decimal">1778.00</Ingot_Length> 
        <Heater_Temp xsi:type="xsd:decimal">1388.80</Heater_Temp> 
        <LS_Temp xsi:type="xsd:decimal">1330.70</LS_Temp> 
        <Heater_Power xsi:type="xsd:decimal">63.50</Heater_Power> 
       </Single_Moment_Snapshot> 
       </Single_Moment_Snapshot> 
      </Growth_Process> 
      </Growth_Process> 
      <Growth_FinishTime xsi:type="xsd:dateTime">2011-03-03T06:48:19</Growth_FinishTime> 
     </Crystal_Growth> 
     </Grower_Run_Section> 
    </Section> 
    </Crucible> 
</Grower_Run> 

好了,所以澄清这里是我完整的查询。

DECLARE @FILES TABLE(FILENAME VARCHAR(20),DEPTH INT,FILE_FLAG INT) 
DECLARE @XML_TABLE TABLE(
    xmlFileName VARCHAR(300), 
    xml_data xml 
) 
DECLARE @xmlFileName VARCHAR(300) 
DECLARE @FILENAME VARCHAR(20) 

INSERT INTO @FILES 
EXEC Master.dbo.xp_DirTree '\\SASSOAPPSRV\Grower XML Files\',1,1 

DECLARE XML_CURSOR CURSOR FOR SELECT FILENAME FROM @FILES 

OPEN XML_CURSOR 
FETCH NEXT FROM XML_CURSOR 
INTO @FILENAME 

WHILE @@FETCH_STATUS = 0 
BEGIN 

SELECT @xmlFileName = '\\SASSOAPPSRV\Grower XML Files\' + @FILENAME 

INSERT INTO @XML_TABLE(xmlFileName, xml_data) 
EXEC(' 
SELECT ''' + @xmlFileName + ''', xmlData 
FROM 
(
    SELECT * 
    FROM OPENROWSET (BULK ''' + @xmlFileName + ''' , SINGLE_BLOB) AS XMLDATA 
) AS FileImport (XMLDATA) 
') 
FETCH NEXT FROM XML_CURSOR 
INTO @FILENAME 

END 
CLOSE XML_CURSOR 
DEALLOCATE XML_CURSOR 

DECLARE @PARSED_XML TABLE(
S VARCHAR(200), 
RUN_ID VARCHAR(20) 
,SECTION_ID VARCHAR(50) 
) 



INSERT INTO @PARSED_XML 
SELECT 
T.xmlFileName AS S, 
    t.xml_data.value('(/Grower_Run/Run_ID)[1]', 'varchar(50)') AS 'RunID', 
    Section.value('(Grower_Run_Section/SectionID)[1]', 'varchar(50)') as 'SectionID' 
FROM 
    @xml_table t 
CROSS APPLY 
    t.xml_data.nodes('/Grower_Run/Crucible/Section') AS Tmp(Section) 

SELECT 
S 
,RUN_ID 
,SECTION_ID 
FROM @PARSED_XML 
WHERE RUN_ID = 'SA1611030B' 
ORDER BY RUN_ID 

这是我得到的结果。

\\SASSOAPPSRV\Grower XML Files\SA1611030B.xml SA1611030B SA1611030B1 

这是问题,因为我需要在单独的行中查看来自两个节点副本的数据。


所以我有以下结构的许多XML文档

<Grower_Run xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Run_ID xsi:type="xsd:string">SA0111023B</Run_ID> 
    <Crucible xsi:type="Crucible"> 
    <Section> 
     <Grower_Run_Section> 
     <SectionID xsi:type="xsd:string">SA0111023B1</SectionID> 
     </Grower_Run_Section> 
    </Section> 
    <Section> 
     <Grower_Run_Section> 
     <SectionID xsi:type="xsd:string">SA0111023B9</SectionID> 
     </Grower_Run_Section> 
    </Section> 
    </Crucible> 
</Grower_Run> 

,我已经导入到其中,我对查询有这样一个

查询的临时表的XML字段
SELECT 
    CAST(XML_DATA.query('data(/Grower_Run/Run_ID)') AS VARCHAR(20)) AS [RUN ID] 
    ,CAST(XML_DATA.query('data(/Grower_Run/Crucible/Section/Grower_Run_Section/SectionID)') AS VARCHAR(50)) AS [SECTION ID] 
FROM @XML_TABLE 

所以问题是我的结果来自“SectionID”标记的多个实例显示在同一行。

RunID | SectionID 
-------------------------- 
SA0111023B | SA0111023B1 SA0111023B9 

当它应该是

RunID  | SectionID 
----------------------------- 
SA0111023B | SA0111023B1 
SA0111023B | SA0111023B9 

如果我有[1]〜然后结束XML查询的这样

CAST(XML_DATA.query('data(/Grower_Run/Crucible/Section/Grower_Run_Section/SectionID)')[1] 

它将丢弃所述第二节ID一起不起作用因为我需要两个。

任何帮助?

回答

4

如果你想从XML文档中选择了多个“行”,你需要使用.nodes() SQL Server中的XML功能 - 是这样的:

SELECT 
    @XMLTable.value('(/Grower_Run/Run_ID)[1]', 'varchar(50)') AS 'RunID', 
    Section.value('(Grower_Run_Section/SectionID)[1]', 'varchar(50)') as 'SectionID' 
FROM 
    @XMLTable.nodes('/Grower_Run/Crucible/Section') AS Tmp(Section) 

FROM子句中的XPath语句基本上定义XML元素的“伪表” - 基于该XPath。因此,您可以在XML中为每个<Section>条目获得一个伪表 - 然后,您可以使用.value()函数选择单个元素。

如果您想选择从包含XML类型的列的表,你可能需要检查到CROSS APPLY命令:

SELECT 
    t.SomeColumn,   
    t.XmlColumn.value('(/Grower_Run/Run_ID)[1]', 'varchar(50)') AS 'RunID', 
    Section.value('(Grower_Run_Section/SectionID)[1]', 'varchar(50)') as 'SectionID' 
FROM 
    dbo.YourTable t 
CROSS APPLY 
    t.XmlColumn.nodes('/Grower_Run/Crucible/Section') AS Tmp(Section) 
+0

我看到你在这里提出的建议,但我在实施时遇到了麻烦。试图应用顶部的建议我得到一个错误:必须声明标量变量“@XML_TABLE”。我正在将我的xml加载到表变量的列中,然后将这些查询从此重要。 – Neberu 2011-03-09 20:14:08

+0

@Neberu:第一种方法是有效的,就是你的XML在一个SQL变量中。如果你有一个表,你需要使用第二种方法 – 2011-03-09 20:16:46

+0

谢谢,我尝试了第二种方法,它查询没有错误,但它似乎只返回节点的第一个实例,就像将[1]放在在上面的问题结尾提到的查询结束。 – Neberu 2011-03-09 20:21:08

1

这将工作...,例如:

pref.value('(OriginatorAgency/text())[1]','varchar(50)'), 
pref.value('(OriginatorAgency/text())[2]','varchar(50)'), 
pref.value('(OriginatorAgency/text())[3]','varchar(50)') 

如果有3个OriginatorAgency项目。