2012-06-14 3 views
0

이것은 간단하며 중괄호를 올바르게 입력하지 않아도 SQL SERVER XML 데이터를 쿼리하는 데 경험이 없으므로 정신이 없습니다.SQL Server 2008의 XML 열에서 WHERE 특성을 사용하는 방법

XML 형식의 열이 포함 된 간단한 테이블 NoSqlField이 있습니다. 이 NULL 또는

<root version="1.0"> 
    <entry key="mykey">1</entry> 
</root> 

나는 < 항목 키 = "의 mykey"> 1 </항목들이 NoSqlField 열의 > 값이 테이블의 모든 행을 원하는 중 하나가 포함되어 있습니다.

where h.NoSqlField.ToString().IndexOf("<entry key=\"mykey\">1</entry>") > -1 

가 결과를 반환하여 LINQ 쿼리, 그래서 확실히 거기

A (가로 .toString()를 사용하기 때문에 오히려 바보).

어떻게 T-SQL에서 동일한 쿼리를 실행할 수 있습니까? 나는 (...와 슬래시, 전체 경로없이) 다양한 변화에

SELECT * FROM mytable WHERE 
NoSqlField.value('(//entry[@key=mykey])[1]','varchar(1)') = '1' 

을 시도했지만 하나의 반환 행을 가지고 적이 없다.

답변

1

해결 방법 1 : 당신은 NoSqlField 열이 //root/entry 요소를 가지고 있으며,이 요소가 1 (내부 텍스트)이 포함되어 있는지 확인하는 다음이 솔루션을 사용할 수 원하는 경우 :

SET ANSI_WARNINGS ON; 
GO 

DECLARE @TestData TABLE (
    ID INT IDENTITY PRIMARY KEY, 
    NoSqlField XML NULL 
); 

INSERT @TestData (NoSqlField) 
SELECT NULL 
UNION ALL 
SELECT ' 
<root version="1.0"> 
    <entry key="mykey">1</entry> 
</root>' 
UNION ALL 
SELECT ' 
<root version="1.0"> 
    <entry key="mykey" anotherkey="myanotherkey">1</entry> 
</root>' 
UNION ALL 
SELECT ' 
<root version="1.0"> 
    <entry key="anotherkey" key2="a">1</entry> 
</root>' 
UNION ALL 
SELECT ' 
<root version="1.0"> 
    <entry key="mykey" key3="3">22</entry> 
</root>'; 

SELECT * 
FROM @TestData t 
WHERE t.NoSqlField.exist('//root/entry[@key="mykey"][text() = "1"]') = 1 

결과 :

ID NoSqlField 
-- --------------------------------------------------------------------------------- 
2 <root version="1.0"><entry key="mykey">1</entry></root> 
3 <root version="1.0"><entry key="mykey" anotherkey="myanotherkey">1</entry></root> 

참고 1 :이 솔루션이 다른 속성 (예 : anotherkey)을 허용한다는 것을 알 수 있습니다.

해결 방법 2 : 당신은 엄격한 필터 (하나 개의 속성으로 entry 요소 : key를)하려면 다음

SELECT * 
FROM 
(
     SELECT * 
       ,t.NoSqlField.exist('//root/entry[@key="mykey"][text() = 1]') AS XmlExist 
       ,t.NoSqlField.query(' 
        let $list := //root/entry/@* 
        for $i in $list 
        where local-name($i) != "key" 
         return <ret value="1"/> 
       ').exist('//ret') AS HasAnotherAttribute 
     FROM @TestData t 
) src 
WHERE src.XmlExist = 1 
AND  src.HasAnotherAttribute = 0 

결과 :

ID NoSqlField            XmlExist HasAnotherAttribute 
-- ------------------------------------------------------- -------- ------------------- 
2 <root version="1.0"><entry key="mykey">1</entry></root> 1  0 

다음이 쿼리를 사용할 수 있습니다 참고 2 : let $list := //root/entry/@*은 (@ *) 속성이 모두 //root/entry 개 요소 인 목록을 작성합니다.

주 3 : local-name()

+0

이 (. 내가 해결 한 시도했지만 확실히 더 공부를합니다 2도) 작동합니다! 그냥 그렇게! 정확히 내가 무엇을 찾고 있었는지. 정말 고마워! – Olaf