2015-09-27 41 views
1

我有一個名爲VPX_EVENT_ARG的表,其中一列ARG_DATA包含XML值。將多行XML值和主鍵合併到一個SQL查詢表中

Table 1 
+----------+-------------------+----------+ 
| EVENT_ID |  ARG_TYPE  | ARG_DATA | 
+----------+-------------------+----------+ 
| 7121001 | vim.vm.ConfigSpec | XML1  | 
| 7121002 | vim.vm.ConfigSpec | XML2  | 
| 7121003 | vim.vm.ConfigSpec | XML3  | 
+----------+-------------------+----------+ 

XML1,XML2和XML3是XML值。他們太長,無法輸入表格。這是真正的價值。實際上它們出現在一行中。

XML1,例如,

<obj xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:vim25" versionId="5.5" xsi:type="VirtualMachineConfigSpec"><changeVersion>2015-09-24T10:02:53.866694Z</changeVersion><files><vmPathName>ds:///vmfs/volumes/54e5d10c-c527b7f3-7eea-a0d3c1f01404/CommVault VM Test/CommVault VM Test.vmx</vmPathName></files><deviceChange><operation>remove</operation><device xsi:type="VirtualDisk"><key>2003</key><deviceInfo><label>Hard disk 4</label><summary>20,971,520 KB </summary></deviceInfo><backing xsi:type="VirtualDiskFlatVer2BackingInfo"><fileName>ds:///vmfs/volumes/54e5d10c-c527b7f3-7eea-a0d3c1f01404/CommVault VM Test/CommVault VM Test_2.vmdk</fileName><diskMode>persistent</diskMode><split>false</split><writeThrough>false</writeThrough><thinProvisioned>false</thinProvisioned><uuid>6000C29b-e652-b5fe-76fa-18f6de988807</uuid><contentId>5bd085f0f9391346751e1e7efffffffe</contentId><digestEnabled>false</digestEnabled></backing><controllerKey>1000</controllerKey><unitNumber>3</unitNumber><capacityInKB>20971520</capacityInKB><shares><shares>1000</shares><level>normal</level></shares><storageIOAllocation><limit>-1</limit><shares><shares>1000</shares><level>normal</level></shares></storageIOAllocation></device></deviceChange></obj> 

我將XML1分離成多行,這樣它會更容易閱讀。

<obj xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:vim25" versionId="5.5" xsi:type="VirtualMachineConfigSpec"><changeVersion>2015-09-24T10:02:53.866694Z</changeVersion><files><vmPathName>ds:///vmfs/volumes/54e5d10c-c527b7f3-7eea-a0d3c1f01404/CommVault VM Test/CommVault VM Test.vmx</vmPathName></files> 

<deviceChange> 
    <operation>remove</operation> 
    <device xsi:type="VirtualDisk"> 
     <key>2003</key> 
     <deviceInfo> 
      <label>Hard disk 4</label> 
      <summary>20,971,520 KB </summary> 
     </deviceInfo> 
     <backing xsi:type="VirtualDiskFlatVer2BackingInfo"> 
     <fileName>ds:///vmfs/volumes/54e5d10c-c527b7f3-7eea-a0d3c1f01404/CommVault VM Test/CommVault VM Test_2.vmdk 
     </fileName> 
     <diskMode>persistent</diskMode> 
     <split>false</split> 
     <writeThrough>false</writeThrough> 
     <thinProvisioned>false</thinProvisioned> 
     <uuid>6000C29b-e652-b5fe-76fa-18f6de988807</uuid> 
     <contentId>5bd085f0f9391346751e1e7efffffffe</contentId> 
     <digestEnabled>false</digestEnabled> 
    </backing> 
    <controllerKey>1000</controllerKey> 
    <unitNumber>3</unitNumber> 
    <capacityInKB>20971520</capacityInKB> 

    <shares><shares>1000</shares><level>normal</level></shares><storageIOAllocation><limit>-1</limit><shares><shares>1000</shares><level>normal</level></shares></storageIOAllocation> 
    </device> 
</deviceChange> 
</obj> 

我想使用MSSQL查詢將XML1提取到表中。

DECLARE @xml XML 
SET @xml = (SELECT ARG_DATA FROM VPX_EVENT_ARG WHERE ARG_ID = 1 AND EVENT_ID = 7121001); --EVENT_ID is fixed. 
WITH XMLNAMESPACES('urn:vim25' AS NS) 

SELECT 
'diskUnit' = ref.value('./NS:device[1]/NS:unitNumber[1]', 'INT'), 
'operation' = ref.value('./NS:operation[1]', 'NVARCHAR(100)'), 
'newSizeKB' = ref.value('./NS:device[1]/NS:capacityInKB[1]', 'BIGINT') 
FROM @xml.nodes('/NS:obj/NS:deviceChange') data(ref) 

嗯,我得到了這個結果。

Table 2 
+------+-----------+-----------+ 
| unit | operation | newSizeKB | 
+------+-----------+-----------+ 
| 1 | edit  | 24117248 | 
| 2 | edit  | 108003328 | 
| 3 | add  | 20971520 | 
+------+-----------+-----------+ 

可以看到,表2是在表1中甚至沒有第一行第一行的只是結果,它只是ARG_DATA它修正EVENT_ID以及第一行。我希望任何人都可以幫忙。

問題1:我想將多行XML值合併到一個表中,而不修復EVENT_ID並將EVENT_ID也放入列中。請假定VPX_EVENT_ARG表包含數百行。

Table3 
+----------+------+-----------+-----------+ 
| EVENT_ID | unit | operation | newSizeKB | 
+----------+------+-----------+-----------+ 
| 7121001 | 1 | edit  | 24117248 | 
| 7121001 | 2 | edit  | 108003328 | 
| 7121001 | 3 | add  | 20971520 | 
| 7121002 | 1 | edit  | 1048576 | 
| 7121002 | 3 | edit  | 52428800 | 
| 7121003 | 3 | edit  | 125829120 | 
| 7121003 | 5 | remove | 83886080 | 
+----------+------+-----------+-----------+ 

問題2:有沒有辦法在不設置XML的情況下使用查詢?我需要爲查詢設置XML,然後我可以使用nodes()。

SET @xml = (SELECT ARG_DATA FROM VPX_EVENT_ARG WHERE ARG_ID = 1 AND EVENT_ID = 7121001); 
. 
. 
FROM @xml.nodes('/NS:obj/NS:deviceChange') data(ref) 

我想知道是否可以這樣做。

FROM (SELECT ARG_DATA FROM VPX_EVENT_ARG WHERE ARG_ID = 1 AND EVENT_ID = 7121001).nodes('/NS:obj/NS:deviceChange') data(ref) 

Error: Incorrect syntax near '.'. Expecting AS, ID, or QUOTED_ID. 

我真的想用這樣的結果作爲表3加入我以前查詢過的表。我很難處理XML,但一直堅持這麼久。順便說一下,我無法更新表格;它受到限制。

回答

2

你可以。使用交叉應用的節點上:

;WITH XMLNAMESPACES('urn:vim25' AS NS) 
SELECT 
    v.EVENT_ID, 
    'diskUnit' = ref.value('./NS:device[1]/NS:unitNumber[1]', 'INT'), 
    'operation' = ref.value('./NS:operation[1]', 'NVARCHAR(100)'), 
    'newSizeKB' = ref.value('./NS:device[1]/NS:capacityInKB[1]', 'BIGINT') 
FROM VPX_EVENT_ARG AS v 
CROSS APPLY v.ARG_DATA.nodes('/NS:obj/NS:deviceChange') data(ref) 

如果列不是XML,我們需要一個子查詢其轉換:

;WITH XMLNAMESPACES('urn:vim25' AS NS) 
SELECT 
v.EVENT_ID, 
'diskUnit' = ref.value('./NS:device[1]/NS:unitNumber[1]', 'INT'), 
'operation' = ref.value('./NS:operation[1]', 'NVARCHAR(100)'), 
'newSizeKB' = ref.value('./NS:device[1]/NS:capacityInKB[1]', 'BIGINT') 
FROM 
(
    SELECT 
     c.EVENT_ID, 
     c.ARG_TYPE, 
     CONVERT(xml,c.ARG_DATA) AS ARG_DATA, 
     c.ARG_ID 
    FROM VPX_EVENT_ARG AS c 
) AS v 
CROSS APPLY v.ARG_DATA.nodes('/NS:obj/NS:deviceChange') data(ref) 
+0

它有錯誤出現,「1號線 的XMLDT方法「節點'只能在xml類型的列上調用。「我發現ARG_DATA是ntext。我必須先將它轉換成XML嗎? – PokePalm

+0

@PokePalm是的,在答案中增加了對話 – Backs

+0

這項工作優雅而有效地幫助了很多。非常感謝您的幫助,Backs! – PokePalm

相關問題