2012-03-21 4 views
1

쿼리 및 값 함수가있는 xml 데이터 열이있는 테이블을 쿼리하려고합니다. 일반 문자열 리터럴을 사용할 때는 모두 괜찮습니다. 그러나 저장 프로 시저에 저장하고 변수를 사용하려고하면 작동하지 않습니다.MSSQL에서 XML 쿼리를 사용하는 저장 프로 시저 매개 변수는 "인수는 문자열 리터럴이어야합니다."

내가 올바른 데이터 유형을 사용하고 있지 않다고 가정하지만 일부 검색 후에는 쿼리 기능이 원하는 데이터 유형을 알 수 없습니다.

예 : 표는 선택 쿼리

select id 
from table 
where xmldata.query('/data/node').value('.', 'VARCHAR(50)') = 'value' 

나에게 내가 원하는 데이터를 얻을 수를 사용하여, 지금

| Id | xmldata       | 
| 1 | <data><node>value</node></data> | 

가 포함되어 있습니다. 내가 저장 프로 시저에서 이것을 사용하고 매개 변수 @xpath varchar(100)를 사용하여 쿼리 방법에 그것을 통과한다면, xmldata.query(@xpath) 은 내가

The argument 1 of the xml data type method "query" must be a string literal. 

내가 추측 오류를 VARCHAR (100) 정확하지를 얻을 수 있지만, 어떤 데이터 타입은 가능한 한 MSSQL을 행복하게 만들 수 있을까요?


업데이트 : 좋습니다. 분명히 "그냥 그"와 같은 쿼리 메서드에 매개 변수를 전달할 수는 없지만 local-name과 함께 sql : 변수를 사용하여 그 일부를 처리 할 수 ​​있습니다. 예를 들어,이 작업은 작동합니다.

declare @xpath VarChar(100) 
set @xpath='node' 
select objectData.query('/data/*[local-name() = sql:variable("@xpath")]') 
       .value('.', 'varchar(100)') as xmldata 
from table 

값은 xmldata 열에서 선택됩니다. 그러나 (!) 루트 노드가 쿼리 함수의 첫 번째 값이어야합니다. 다음은 쿼리 경로는 어떻게하지

declare @xpath VarChar(100) 
set @xpath='/data/node' 
select objectData.query('*[local-name() = sql:variable("@xpath")]') 
       .value('.', 'varchar(100)') as xmldata 
from table 

통지 변수에 "위로 이동"할 것이다. 조사를 계속하겠습니다.

+1

전체 XPath 표현식을 변수 (동적 SQL 제외)로 바꾸는 방법이 없습니다. 여러분은'local-name()'을 사용하여 노드 이름을 변수와 비교할 수 있습니다. 루트 노드 이름이 마음에 들지 않는다면'@ * [local-name() = sql : variable ("@ xpath"]]'를 사용하여'@xpath '와 일치하는 모든 노드를 깊이 검색 할 수 있습니다 '어디서나 XML에 위치합니다. –

+0

@MikaelEriksson : 오, 알았어요. 두 배의 '//'가 효과가 있다고 생각하지는 않았지만 팁을 주셔서 감사합니다. 나는 그 중 하나를 사용하거나 그냥 매개 변수를 사용하지 않을 것 같아요 .. – Patrick

답변

3

literalvariable의 반대입니다. 이 메시지는 변수를 첫 번째 인수로 query에 전달할 수 없음을 의미합니다. 당신이 볼 수 있듯이

declare @sql varchar(max) 
set @sql = 'select id from table where xmldata.query(''' + @path + 
    ''').value(''.'', ''VARCHAR(50)'') = ''value''' 
exec @sql 

, 동적 SQL은 매우 읽을 수있는 코드가 발생하지 않습니다 그 주위

한 가지 방법은 동적 SQL이다. 나는 확실하게 대안을 조사 할 것이다.

편집 : local-name()의 제안 사항은 노드 이름에 적용됩니다.

declare @nodename varchar(max) 
set @nodename = 'node' 
... 
where xmldata.query('//*[local-name()=sql:variable("@nodename")]') 
      .value('.', 'varchar(50)') = 'value' 

경로에 해당하는 것으로 보이지 않습니다.

+0

흠 .. 좋아.그래서 가장 쉬운 방법은 변수를 사용하지 않고 "정적"xpaths를 사용하는 것입니다. :) – Patrick

+2

잠깐 ... 잠깐만 ... [XPath의 SQL 변수 참조] 할 수있는 것처럼 보입니다. (http://msdn.microsoft.com/en-us/library/ms188254.aspx) – Andomar

+0

예, http : //를 찾았습니다. /stackoverflow.com/questions/5965000/sql-xml-xquery-data-query-using-a-variable-in-the-node-selection이 것을 참고하는 것 같습니다. 'sql-variable'을 사용하는 것만으로는 효과가 없지만, 재미있는'* [local-name (.) ='로 해결됩니다. – Patrick