2012-11-26 2 views
0

테이블의 SQL Server XML 데이터 열에 일부 데이터가 저장되어 있습니다. 그것은 HTML 콘텐트 (전자 메일로 전송 됨)을 구성하는 데 사용되며 정상적으로 작동합니다. 그러나 지금은 일부 데이터를 변경하고 싶지만 원하는 비트 만 적용하려면 올바른 주문을 찾지 못하는 것 같습니다.SQL XML 열의 노드 내용을 수정하려면 어떻게합니까?

다음 예를 참조하십시오.

declare @s1 varchar(max); 
declare @s2 varchar(max); 
declare @s3 varchar(max); 

-- rough approximation of my data 
set @s1 = '<email sender="bob"><html><body><table><tbody><tr><td><b>' 
set @s2 = '</b></td></tr><tr><td><b>' 
set @s3 = '</b></td></tr></tbody></table></body></html></email>' 

declare @t table (id int, data xml) 

insert into @t values (1, @s1 + 'Hello World' + @s2 + 'Goodbye cruel world' + @s3) 
insert into @t values (2, @s1 + 'Hello World' + @s2 + 'I''m leaving you today' + @s3) 
insert into @t values (3, @s1 + 'Hello World' + @s2 + 'Goodbye, goodbye, goodbye' + @s3) 

select data from @t 

update @t -- change sender to "fred" 
set data.modify('replace value of (/email/@sender)[1] with "fred"') 

select data from @t 

select data,x.nd.value('b[1]','varchar(max)') -- find the "hello world" bits 
from @t 
cross apply data.nodes('email/html/body/table/tbody/tr/td') as x(nd) 
where x.nd.value('b[1]','varchar(max)') = 'Hello World' 

내가을 (내가 밖으로 일을했다고 생각)은 "보낸 사람"데이터 하고 "안녕하세요"데이터를 변경하려면 - 내가 찾을 수 있습니다,하지만 난 방법을 모르는 변화. 나는 "크로스 적용"문법으로 어떤 일이 벌어지는 지 잘 모르겠다. XPath 만 쓰면 "where"절없이 "Hello World"노드 만 찾을 수있을 것이라고 생각한다.

내 테이블에는 약 9 개의 행만 있습니다. 따라서 필요한 경우 9 개의 업데이트 명령을 쓸 수 있으며 이는 일회성 데이터 유지 관리 작업입니다.

도움을 주시면 감사하겠습니다.

편집 :

는 그 일이이 방법이 있나요?

update @t 
set data.modify('replace value of (email/html/body/table/tbody/tr/td/b/text())[1] with "bonjour monde"') 
from @t 
cross apply data.nodes('email/html/body/table/tbody/tr/td') as x(nd) 
where x.nd.value('b[1]','varchar(max)') = 'Hello World' 

감사합니다.

답변

1

거의 :) 편집에서 귀하의 예는 email/html/body/table/tbody/tr/td/b 업데이트하지만, WHERE 절은 어떤email/html/body/table/tbody/tr/td을 찾습니다. 따라서 두 개의 tr이 있고 두 번째 필터가 첫 번째 필터를 업데이트하는 이메일을 가지고있는 경우. 예 :

insert into @t values (4, '<email sender="bob"><html><body><table><tbody> 
    <tr><td><b>Ciao mondo!</b></td></tr><tr><td><b>Goodbye, goodbye, goodbye</b></td></tr> 
    <tr><td><b>Hello World</b></td></tr><tr><td><b>Can''t get rid of me!</b></td></tr> 
    </tbody></table></body></html></email>'); 

는 XML 위에서 올바르게 업데이트되지 않는다 : 실제로 필터와 일치하지 않는 제 TR 변경되며,이 변경되었다해야 하나이지만 그 영향을받지 않고 제를 떠날 것이다. 이것을 접근하는 방법은 여러 가지가 있습니다. 개인적으로 나는 XPath/XQuery를 .modify에 만들 것이고 나를 위해 일을 할 것이다. 나는 또한 XML.exist이 충분 때 십자가의 사용이 적용 비평 것 :

update @t 
set data.modify('replace value of (email/html/body/table/tbody/tr/td/b[.="Hello World"]/text())[1] with "bonjour monde"') 
from @t 
where data.exist('email/html/body/table/tbody/tr/td/b[.="Hello World"]') = 1; 

이 더 정확합니다,하지만 그것은 한 번에 하나의 XML 요소가 (변경 될 수 반복적으로 실행해야합니다 즉, 두 경우. tr에 Hello World가있는 경우 수정은 첫 번째 업데이트 만 업데이트합니다).

첫 번째 업데이트가 작업을 수행했을 가능성이 높기 때문에 이러한 모든 사항은 학구적 인 내용 일 가능성이 큽니다. 그러나 나중에 참고할 수 있습니다. BTW, 배울 방법 XPath filters work, 그들은 대단히 도움이됩니다.

+0

팁을 보내 주셔서 감사합니다. XPath 필터. –

관련 문제