2012-11-27 92 views
5

我有一個簡單的XML在XML列使用XQUERY更新SQL Server xml列?

<Bands> 
    <Band> 
     <Name>beatles</Name> 
     <Num>4</Num> 
     <Score>5</Score> 
    </Band> 
    <Band> 
     <Name>doors</Name> 
     <Num>4</Num> 
     <Score>3</Score> 
    </Band> 
</Bands> 

我設法與更新列:

-----just update the name to the id)---- 
    UPDATE tbl1 
    SET [myXml].modify('replace value of (/Bands/Band/Name/text())[1] 
    with sql:column("id")') 

一切都很好。

問題#1

如何使用這個查詢來UDPATE值來id+"lalala"

UPDATE tbl1 
    SET [myXml].modify('replace value of (/Bands/Band/Name/text())[1] 
    with sql:column("id") + "lalala"') 

錯誤=的XQuery [tbl1.myXml.modify()]:的參數'+'必須是單個數字原始類型

問題1

比方說我不想更新第一個記錄([1]),但我想udpate(與上面相同的更新)只有在score>4

我可以在XPath ofcourse寫:

replace value of (/Bands/Band[Score>4]/Name/text())[1]

,但我不想這樣做在XPath。 Where子句中沒有這樣做的正常方法嗎?

類似:

UPDATE tbl1 
    SET [myXml].modify('replace value of (/Bands/Band/Name/text())[1] 
    with sql:column("id") where [...score>4...]') 

here is the online sql

回答

6

如果你想連接字符串,你應該使用concat,如果你的情況下id是一個整數,你需要將它轉換爲concat函數中的字符串。

在where子句中,您可以篩選要更新的表的行,但不能指定要在XML中更新的節點。這必須在xquery表達式中完成。但是,您可以在where子句中使用exist來篩選出真正需要更新的行。

update tbl1 
set myXml.modify('replace value of (/Bands/Band[Score > 4]/Name/text())[1] 
        with concat(string(sql:column("id")), "lalalala")') 
where myXml.exist('/Bands/Band[Score > 4]') = 1 
+1

他們爲什麼要這樣做?[1]'東西?他們不覺得我可能想更新'超過1個元素'嗎? –

+0

@RoyiNamir說「Expression1必須是一個靜態單例」的文檔。是[here](http://msdn.microsoft.com/en-us/library/ms190675.aspx)。 'insert'是相同的,但'delete'可以刪除多個節點。我不知道他們爲什麼選擇這樣做,但如果允許的話,最終會出現一些奇怪的情況,即修改後的節點會更改發現需要修改的節點的謂詞。如果你需要更新多個節點,你必須在while循環中完成。 –

+0

謝謝。我選擇這個答案是因爲它不那麼長和更具可讀性。但非常感謝這兩個答案。 –

5

Q1:

;with t as (select convert(varchar(10),id) + 'lalala' id2, * from #tbl1) 
    UPDATE t 
    SET [myXml].modify('replace value of (/Bands/Band/Name/text())[1] 
    with sql:column("id2")'); 

注:你有沒有意識到,這僅更新第一個樂隊的名字的名字,而不是所有樂隊?

第二Q1:

你就是不行。特別是因爲(/Bands/Band[Score<4]/Name/text())[1](我更改爲<)特別針對問題中xml示例中的門Band。另一方面,WHERE子句將在XML中工作,而不是路徑中的特定級別。例如一個非常錯誤的解釋:

;with t as (
    select a.*, n.m.value('.','int') Score 
    from #tbl1 a 
    cross apply myXml.nodes('/Bands/Band/Score') n(m) -- assume singular 
) 
    UPDATE t 
    SET [myXml].modify('replace value of (/Bands/Band/Name/text())[1] 
    with sql:column("id")') 
    where Score < 4 

因爲至少有一個條帶的XML與比分< 4,XML得到更新。 但是,因爲xml.modify只在第一場比賽中有作用,所以第一個樂隊的名字被更新,而不是匹配得分過濾器的名字。