2015-10-26 64 views
2

我的目標是打破這個XML,這樣我就可以將每個記錄行的Field元素插入到SQL表中。 我無法弄清楚如何遍歷網格層次結構。我已經能夠運行一些針對它的xquery 命令,但只能在最高級別上顯示,如下所示。請幫助完成下列操作: 爲每個行的每個字段執行字段元素值。T-sql用特殊元素解析XML節點

declare @Responsetext varchar(8000) 
set @Responsetext = 
'<GridResponse xmlns="http://abcd.abcd.net/aapi/2009/08/"> 
    <Brand id="1111">API Starter App</Brand> 
    <User>AAA_API</User> 
    <Grids> 
    <Grid type="subscriber"> 
     <Record row="1"> 
     <Fields> 
      <Field element="subscriber_id">111107293</Field> 
      <Field element="bounce_date" /> 
      <Field element="cancellation_mailing_instance_id" /> 
      <Field element="cancellation_message" /> 
      <Field element="cancellation_date" /> 
      <Field element="email">[email protected]</Field> 
      <Field element="is_repeated_bouncer">0</Field> 
      <Field element="is_unsubscriber">0</Field> 
      <Field element="modified_date">2015-04-07T13:19:09.3400000Z</Field> 
      <Field element="service_since_date">2011-10-17T13:23:38.7800000Z</Field> 
      <Field element="user_id" /> 
     </Fields> 
     </Record> 
     <Record row="2"> 
     <Fields> 
      <Field element="subscriber_id">111169135</Field> 
      <Field element="bounce_date" /> 
      <Field element="cancellation_mailing_instance_id" /> 
      <Field element="cancellation_message" /> 
      <Field element="cancellation_date" /> 
      <Field element="email">[email protected]</Field> 
      <Field element="is_repeated_bouncer">0</Field> 
      <Field element="is_unsubscriber">0</Field> 
      <Field element="modified_date">2014-12-15T17:30:18.2230000Z</Field> 
      <Field element="service_since_date">2011-10-19T14:11:26.6370000Z</Field> 
      <Field element="user_id" /> 
     </Fields> 
     </Record> 
    </Grid> 
    </Grids> 
</GridResponse> 
' 

該代碼給了我節點樹,但我無法弄清楚如何調整這個來隔離8級深的字段值。

--This CTE gives you the Node Tree 
WITH Xml_CTE AS 
(
    SELECT 
     CAST('/' + node.value('fn:local-name(.)', 
      'varchar(100)') AS varchar(100)) AS name, 
     node.query('*') AS children 
    FROM @XmlResponse.nodes('/*') AS roots(node) 

    UNION ALL 

    SELECT 
     CAST(x.name + '/' + 
      node.value('fn:local-name(.)', 'varchar(100)') AS varchar(100)), 
     node.query('*') AS children 
    FROM Xml_CTE x 
    CROSS APPLY x.children.nodes('*') AS child(node) 
) 
SELECT distinct name 
FROM Xml_CTE x 
OPTION (MAXRECURSION 1000) 

如果我推了XML到一個表,而不是使用可變的,我能得到這樣的根節點,但還是不能讓到現場的水平。

--Parent Node -- Returns GridResponse 
SELECT 
( 
SELECT 
c.value('local-name(.)', 'nvarchar(50)') 
FROM 
xmldata.nodes('/*') AS r(c) 
) AS RootParent 
FROM [dbo].subscriber_xml 

我可以查詢是否存在節點,並獲取根和品牌子節點,但不是網格子節點。這很混亂,爲什麼一個人工作,另一個不工作。

SELECT XmlData.exist('(/*[1][contains(local-name(.),"GridResponse")])') 
FROM [dbo].subscriber_xml 

SELECT XmlData.exist('(/*/*[1][contains(local-name(.),"Brand")])') 
FROM [dbo].subscriber_xml 

SELECT XmlData.exist('(/*/*[1][contains(local-name(.),"Grids")])') 
FROM [dbo].subscriber_xml 
+0

也許這會幫助你http://stackoverflow.com/questions/13195922/how-to-query -xml-column-in-tsql?rq = 1 –

回答

0

這是我的建議(請改變你的@Responsetext聲明XML):

WITH XMLNAMESPACES(DEFAULT 'http://abcd.abcd.net/aapi/2009/08/') 
SELECT OneRecord.value('@row','varchar(max)') AS RowID 
     ,OneRecord.value('(Fields/Field[@element="subscriber_id"])[1]','varchar(max)') AS subscriber_id 
     ,OneRecord.value('(Fields/Field[@element="bounce_date"])[1]','varchar(max)') AS bounce_date 
     ,OneRecord.value('(Fields/Field[@element="cancellation_mailing_instance_id"])[1]','varchar(max)') AS cancellation_mailing_instance_id 
     ,OneRecord.value('(Fields/Field[@element="cancellation_message"])[1]','varchar(max)') AS cancellation_message 
     ,OneRecord.value('(Fields/Field[@element="cancellation_date"])[1]','varchar(max)') AS cancellation_date 
     ,OneRecord.value('(Fields/Field[@element="email"])[1]','varchar(max)') AS email 
     ,OneRecord.value('(Fields/Field[@element="is_repeated_bouncer"])[1]','varchar(max)') AS is_repeated_bouncer 
     ,OneRecord.value('(Fields/Field[@element="is_unsubscriber"])[1]','varchar(max)') AS is_unsubscriber 
     ,OneRecord.value('(Fields/Field[@element="modified_date"])[1]','varchar(max)') AS modified_date 
     ,OneRecord.value('(Fields/Field[@element="service_since_date"])[1]','varchar(max)') AS service_since_date 
     ,OneRecord.value('(Fields/Field[@element="user_id"])[1]','varchar(max)') AS user_id 
--INTO tempTable 
FROM @Responsetext.nodes('/GridResponse/Grids/Grid/Record') AS Records(OneRecord) 

這將顯示在一個表網格數據。 只需在INTO tempTable之前拿走--並設置您喜歡的表名。這將創建一個具有給定結構的表格並將其填入數據。

還有一點:你應該根據你的數據選擇數據類型。我拿了varchar(max)爲所有,但你可能會想要將此更改爲int,datetime或任何其他...

+0

謝謝Shnugo,工作很好。你搖滾! –

+1

@KWhiteside,嗨,我很高興閱讀,這可以幫助你!由於你是新手,請注意,專業人士在這裏給出答案,渴望聲望點。如果您的答案幫助您解決問題,那將是非常友善的答案,您應該將其標記爲已接受的答案,這將向其他人展示此問題已解決。謝謝! – Shnugo