2012-11-27 37 views
5

Tôi có một xml đơn giản trong một cột XMLCập nhật cột xml SQL server bằng XQUERY?

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

Tôi đã cố gắng cập nhật các cột với:

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

Tất cả tốt.

Câu hỏi # 1

Làm thế nào tôi có thể sử dụng truy vấn này để udpate giá trị để id+"lalala":

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

Lỗi = XQuery [tbl1.myXml.modify()]: Những lý luận về '+' phải là một kiểu số nguyên duy nhất

Câu hỏi # 1

Giả sử tôi không muốn cập nhật bản ghi đầu tiên ([1]), nhưng tôi muốn udpate (cùng một cập nhật như trên) chỉ ở những nơi score>4.

tôi có thể viết ofcourse trong xpath:

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

Nhưng tôi không muốn làm điều đó trong XPath. Không phải là một cách bình thường để làm điều này với một mệnh đề Where?

cái gì đó như:

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

Trả lời

6

Nếu bạn muốn nối các chuỗi, bạn nên sử dụng concat và nếu id trong trường hợp của bạn là số nguyên bạn cần phải truyền chuỗi đó thành một chuỗi trong hàm concat.

Trong mệnh đề where bạn có thể lọc các hàng của bảng để cập nhật, bạn không thể chỉ định các nút cần cập nhật trong XML. Điều đó phải được thực hiện trong biểu thức xquery. Tuy nhiên, bạn có thể sử dụng exist trong mệnh đề where để lọc ra các hàng thực sự cần cập nhật.

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

tại sao họ làm điều này '[1]'? Họ không nghĩ rằng có lẽ tôi muốn cập nhật 'hơn 1 phần tử'? –

+0

@RoyiNamir Tài liệu nói rằng "Expression1 phải là một singleton thống kê." là [ở đây] (http://msdn.microsoft.com/en-us/library/ms190675.aspx). Nó tương tự cho 'chèn' nhưng' xóa' có thể xóa nhiều hơn một nút. Tôi thực sự không biết tại sao họ chọn làm như vậy nhưng nếu nó được cho phép bạn có thể kết thúc trong một số tình huống kỳ lạ nơi các nút đã sửa đổi thay đổi vị từ tìm thấy các nút cần sửa đổi ngay từ đầu. Nếu bạn cần cập nhật nhiều hơn một nút, bạn phải thực hiện nó trong một vòng lặp while. –

+0

Cảm ơn. Tôi chọn câu trả lời này vì nó ít lâu và dễ đọc hơn. Nhưng cảm ơn rất nhiều cho cả hai câu trả lời! –

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")'); 

Lưu ý: Bạn có nhận ra rằng đây sẽ cập nhật tên của chỉ tên ban nhạc đầu tiên, không phải tất cả ban nhạc?

Q1 2:

Không bạn không thể. Đặc biệt là kể từ (/Bands/Band[Score<4]/Name/text())[1] (Tôi đã thay đổi thành <) nhắm mục tiêu cụ thể đến các cửa ra vào của Ban nhạc trong ví dụ xml của bạn trong câu hỏi. Mặt khác, mệnh đề WHERE sẽ làm việc trên XML, thay vì một mức cụ thể trong đường dẫn. ví dụ. giải thích rất sai:

;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 

Vì có ít nhất một Băng trong xml với điểm số < 4, XML được cập nhật. HOWEVER, bởi vì xml.modify chỉ hoạt động ONCE trong lần khớp đầu tiên, tên ban nhạc đầu tiên được cập nhật chứ không phải tên phù hợp với bộ lọc điểm.

Các vấn đề liên quan