2016-11-21 55 views
2

我需要將數據從一個表中下面的XML格式輸出:環流式

<studentid="000011111"> 
    <academic_goal type="official"> 
      <program_group> 
        <program type="catalog">2014-16</program> 
        <program type="degree">BS</program> 
        <program type="major">PS</program> 
        <program type="concentration">PCC</program> 
      </program_group> 
      <program_group> 
        <program type="catalog">2014-16</program> 
        <program type="degree">BS</program> 
        <program type="minor">HI</program> 
      </program_group> 
    </academic_goal> 
</studentid> 

到目前爲止,我所擁有的是:

<studentid="000011111"> 
    <academic_goal type="official"> 
     <program_group> 
     <program type="catalog">2014-16</program> 
     <program type="degree">BS</program> 
     <program type="major">PS</program> 
     <program type="minor">HI</program> 
     <program type="concentration">PCC</program> 
     </program_group> 
    </academic_goal> 
</studentid> 

我怎麼能遍歷這個信息,以便未成年人在自己的program_group標籤(以及目錄和學位)?

這裏的表結構:

CREATE TABLE [dbo].[StudentProgramData](
    [StudentID] [nvarchar](10) NULL, 
    [Catalog] [nvarchar](10) NULL, 
    [Degree] [nvarchar](10) NULL, 
    [Major] [nvarchar](50) NULL, 
    [Minor] [nvarchar](50) NULL, 
    [Concentration] [nvarchar](50) NULL) 

的樣本數據:

insert into StudentProgramData 
values 
('000011111', '2014-16', 'BS', 'PS', 'HI', 'PCC'), 
('000022222', '2012-14', 'BA', 'MK', 'BI', 'ESO'), 
('000033333', '2012-14', 'BS', 'MB', NULL, 'AUE'), 
('000044444', '2014-16', 'ME', 'PS', 'HI', NULL), 
('000055555', '2010-12', 'MD', 'PS', NULL, 'PCC') 

我包括5個樣本記錄,但我只以上顯示的第一個學生。

到目前爲止我的代碼的循環是:

(select 
    ltrim(rtrim(StudentProgramData.catalog)) as [program/@catalog], 
    ltrim(rtrim(StudentProgramData.degree)) as [program/@degree], 
    ltrim(rtrim(StudentProgramData.major)) as [program/@major], 
    ltrim(rtrim(StudentProgramData.minor)) as [program/@minor], 
    ltrim(rtrim(StudentProgramData.concentration)) as [program/@concentration] 

    from StudentProgramData 

for xml path('program'), type).query(' 
    <academic_goal type="official"> 
    { 
    for $program in /program 
     return 
      <program_group> 
       {$program/Name} 
       <program type="catalog">{data($program/program/@year)}</program> 
       <program type="degree">{data($program/program/@degree)}</program> 
       <program type="major">{data($program/program/@major)}</program> 
       <program type="minor">{data($program/program/@minor)}</program> 
       <program type="concentration">{data($program/program/@concentration)}</program> 
      </program_group> 
    } 
    </academic_goal>') 

任何幫助,您可以提供非常感謝。

+1

正如有人已經指出他們的答案但沒有拼寫出來,是無效的XML。沒有屬性的情況下,您的節點不能擁有自主標識符。 有效。 – djangojazz

+0

這個問題解決了嗎?你需要進一步的幫助嗎?請允許我提示一個提示:如果這個問題已經解決,那麼在(最佳)答案的投票櫃檯下面勾選驗收檢查將會非常友善。這將1)標記這個問題已解決2)使追隨者更容易找到最佳的解決方案3)支付點給回答者和4)支付點給你。既然你已經跨越了15分的邊界,你還需要額外的投票。這是SO的方式來說聲謝謝。快樂編碼! – Shnugo

回答

1

我敢肯定有人會在手腕上狠狠地揍我(@Shnugo,你在哪裏?),但這就是我得到的。這可能不是最好的,毫無疑問,有人會給你更好的答案。但這是你可以在此期間使用的東西。

SELECT 
    studentId AS [student/@id], 
    'official' AS [student/academic_goal/@type], 
    (
     SELECT 
      (
       SELECT 
        'catalog' AS [program/@type], 
        ltrim(rtrim(catalog)) AS [program] 
       FOR XML 
        PATH(''), TYPE 
      ), 
      (
       SELECT 
        'degree' AS [program/@type], 
        ltrim(rtrim(degree)) AS [program] 
       FOR XML 
        PATH(''), TYPE 
      ), 
      (
       SELECT 
        'major' AS [program/@type], 
        ltrim(rtrim(major)) AS [program] 
       FOR XML 
        PATH(''), TYPE 
      ), 
      (
       SELECT 
        'concentration' AS [program/@type], 
        ltrim(rtrim(concentration)) AS [program] 
       FOR XML 
        PATH(''), TYPE 
      ) 
     FOR XML 
      PATH('program_group'), TYPE 
    ) AS [student/academic_goal], 
    (
     SELECT 
      (
       SELECT 
        'catalog' AS [program/@type], 
        ltrim(rtrim(catalog)) AS [program] 
       FOR XML 
        PATH(''), TYPE 
      ), 
      (
       SELECT 
        'degree' AS [program/@type], 
        ltrim(rtrim(degree)) AS [program] 
       FOR XML 
        PATH(''), TYPE 
      ), 
      (
       SELECT 
        'minor' AS [program/@type], 
        ltrim(rtrim(minor)) AS [program] 
       FOR XML 
        PATH(''), TYPE 
      ) 
     FOR XML 
      PATH('program_group'), TYPE 
    ) AS [student/academic_goal] 
FROM 
    StudentProgramData 
FOR XML 
    PATH(''), ROOT('students'); 

產地:

<students> 
    <student id="000011111"> 
    <academic_goal type="official"> 
     <program_group> 
     <program type="catalog">2014-16</program> 
     <program type="degree">BS</program> 
     <program type="major">PS</program> 
     <program type="concentration">PCC</program> 
     </program_group> 
     <program_group> 
     <program type="catalog">2014-16</program> 
     <program type="degree">BS</program> 
     <program type="minor">HI</program> 
     </program_group> 
    </academic_goal> 
    </student> 
    <student id="000022222"> 
    <academic_goal type="official"> 
     <program_group> 
     <program type="catalog">2012-14</program> 
     <program type="degree">BA</program> 
     <program type="major">MK</program> 
     <program type="concentration">ESO</program> 
     </program_group> 
     <program_group> 
     <program type="catalog">2012-14</program> 
     <program type="degree">BA</program> 
     <program type="minor">BI</program> 
     </program_group> 
    </academic_goal> 
    </student> 
    <student id="000033333"> 
    <academic_goal type="official"> 
     <program_group> 
     <program type="catalog">2012-14</program> 
     <program type="degree">BS</program> 
     <program type="major">MB</program> 
     <program type="concentration">AUE</program> 
     </program_group> 
     <program_group> 
     <program type="catalog">2012-14</program> 
     <program type="degree">BS</program> 
     <program type="minor" /> 
     </program_group> 
    </academic_goal> 
    </student> 
    <student id="000044444"> 
    <academic_goal type="official"> 
     <program_group> 
     <program type="catalog">2014-16</program> 
     <program type="degree">ME</program> 
     <program type="major">PS</program> 
     <program type="concentration" /> 
     </program_group> 
     <program_group> 
     <program type="catalog">2014-16</program> 
     <program type="degree">ME</program> 
     <program type="minor">HI</program> 
     </program_group> 
    </academic_goal> 
    </student> 
    <student id="000055555"> 
    <academic_goal type="official"> 
     <program_group> 
     <program type="catalog">2010-12</program> 
     <program type="degree">MD</program> 
     <program type="major">PS</program> 
     <program type="concentration">PCC</program> 
     </program_group> 
     <program_group> 
     <program type="catalog">2010-12</program> 
     <program type="degree">MD</program> 
     <program type="minor" /> 
     </program_group> 
    </academic_goal> 
    </student> 
</students> 
+0

謝謝!將嘗試一下。 – RAR

+0

我需要將它嵌入到我有更大的查詢中。當我按原樣運行它時,它運行良好,但是當我在較大的查詢中運行它時,出現錯誤:「當子查詢未與EXISTS一起引入時,只能在選擇列表中指定一個表達式。「 – RAR

+0

@RAR沒有看到你有的查詢,我只是猜測,但我假設你有一個子查詢,旨在生成XML沒有'FOR XML PATH(...'子句。 –

1

與格式棘手的事情是具有相同名稱<program>許多節點的使用。由於引擎需要先構建屬性,因此無法添加值,然後再次將屬性添加到相同節點。引擎至少是這樣認爲的。

訣竅:在中間添加一個空元素。這將告訴發動機,最後一個要關閉。試試像這樣:

SELECT StudentID AS [@id] 
     ,(
     SELECT 'official' AS [@type] 
       ,(
        SELECT 'catalog' AS [program/@type] 
          ,spd.[Catalog] AS [program] 
          ,'' 
          ,'degree' AS [program/@type] 
          ,spd.[Degree] AS [program] 
          ,'' 
          ,'major' AS [program/@type] 
          ,spd.[Major] AS [program] 
          ,'' 
          ,'concentration' AS [program/@type] 
          ,spd.[Concentration] AS [program] 
        FOR XML PATH('program_group'),TYPE 
       ) 
       ,(
        SELECT 'catalog' AS [program/@type] 
          ,spd.[Catalog] AS [program] 
          ,'' 
          ,'degree' AS [program/@type] 
          ,spd.[Degree] AS [program] 
          ,'' 
          ,'minor' AS [program/@type] 
          ,spd.[Minor] AS [program] 
        FOR XML PATH('program_group'),TYPE 
       ) 
     FROM StudentProgramData AS spd 
     WHERE s.StudentID=spd.StudentID 
     FOR XML PATH('academic_goal'),TYPE 
     ) 
FROM StudentProgramData AS s 
FOR XML PATH('student')--,ROOT('root') --Do you need a root node? Probably yes, if more than 1 student... 
+0

我還在爲之苦苦掙扎,不知道那個空的元素訣竅,很好知道:)雖然有點髒......我不太喜歡SQL Server如何實現XML選擇。記錄在哪裏? –

+1

@TT我trie d解釋發生了什麼[這裏](http://stackoverflow.com/a/29234102/569436)。不知道這個技巧是否由Microsoft明確記錄,但正如我所看到的那樣,這種行爲是它使用'for xml'創建XML的規則的唯一方式。 –

+1

@MikaelEriksson謝謝Michael,我現在看到:) –

2

另一種方法是爲每個程序組創建派生表/ unpivot。

select SPD.StudentID as '@id', 
     (
     select 'official' as '@type', 
       (
       select V.Type as '@type', 
        V.Value as '*' 
       from (values('catalog', SPD.Catalog), 
          ('degree', SPD.Degree), 
          ('major', SPD.Major), 
          ('concentration', SPD.Concentration)) as V(Type, Value) 
       for xml path('program'), root('program_group'), type 
      ), 
       (
       select V.Type as '@type', 
        V.Value as '*' 
       from (values('catalog', SPD.Catalog), 
          ('degree', SPD.Degree), 
          ('minor', SPD.Minor)) as V(Type, Value) 
       for xml path('program'), root('program_group'), type 
      ) 
     for xml path('academic_goal'), type 
     ) 
from dbo.StudentProgramData as SPD 
for xml path('student'); 
+1

太棒了! Upvote從我身邊...最後這是一個可讀性和可維護性的問題... – Shnugo