2009-10-09 2 views
6

xml 데이터를 저장하는 데 사용되는 테이블에 varchar 열이 있습니다. 그래, 내가 사용해야하는 xml 데이터 형식을 알고 있지만 xml 데이터 형식을 사용할 수 있기 전에이 생각했다 그래서 varchar 내가 지금 사용해야하는 것입니다 생각합니다. :) 저장varchar 필드에서 SQL Server XML 문자열 구문 분석

데이터는 다음과 유사합니다

<xml filename="100100_456_484351864768.zip" 
    event_dt="10/5/2009 11:42:52 AM"> 
    <info user="TestUser" /> 
</xml> 

내가이 경우 "456"이 될 것이라고 두 개의 밑줄 사이의 숫자를 얻기 위해 파일 이름을 구문 분석 할 필요가있다. 파일 이름의 첫 번째 부분은 길이가 변경되면 안되지만 가운데 번호는 변경됩니다. 첫 번째 부분의 길이가 변경되면 작동하는 솔루션이 필요합니다 (변경해서는 안된다는 것이 항상 변할 것임을 알기 때문에 변경됩니다).

내가 지금 가지고있는 내용은 XQuery를 사용하여 파일 이름을 꺼내는 것이므로 곧바로 문자열 조작보다 낫다고 생각했기 때문입니다. 이 작업을 수행하려면 문자열을 XML로 변환해야하지만 XQuery 전문가는 아니기 때문에 문제가 발생합니다. XQuery (substring-before)에 대한 함수를 찾았지만 작동시키지 못했습니다. SQL Server에서 함수가 작동하는지조차 모르겠습니다. 쉽게이 작업을 수행 할 수있는 XQuery 함수가있을 수 있지만이를 모르고 있습니다. 나는 다음 몇 가지를 할 문자열이 다시 CAST 할 수있을 거라고 생각 것이에서

select CAST(parms as xml).query('data(/xml/@filename)') as p 
from Table1 

을 :

그래서, 나는 다음과 유사한 쿼리 테이블에서 파일 이름을 얻을 instring 또는 charindex 함수를 사용하여 밑줄이 어디에 있는지 파악하고 필요한 부분을 골라내는 부분 문자열 함수로 모든 것을 캡슐화 할 수 있습니다. 너무 멀리 가지 않으면이 방법으로 마침내 얻을 수 있다고 확신하지만 더 쉬운 방법이 있어야한다는 것을 알고 있습니다. 이 방법은 SQL 문에서 읽을 수없는 커다란 필드를 만들 것입니다. 비록 SQL 문에서 함수를 옮기더라도 계속 진행되고있는 상황을 파악하려고 혼란 스러울 수 있습니다.

단순한 문자열 조작으로 보이기 때문에 이보다 더 쉽습니다. 아마도 누군가 나를 올바른 방향으로 인도 할 수 있습니다. 감사합니다.

+1

어떤 버전의 SQL Server입니까? –

+0

죄송합니다. 지금까지이 설명을 보지 못했습니다. 현재 SQL Server 2008을 사용하고 있습니다. – Dusty

답변

5

당신은 이것에 대한 XQuery를 사용할 수 있습니다 - 단지 유효한 파일 이름과 경로를 개최 충분히 당신에게 VARCHAR (260)를 제공

SELECT 
    CAST(parms as xml).value('(/xml/@filename)[1]', 'varchar(260)') as p 
FROM 
    dbo.Table1 

- 지금 당신은 문자열을 등 SUBSTRING

마크와 함께 작업 할 수 있습니다 : 당신의 문을 변경

+0

응답 해 주셔서 감사합니다.하지만 .value 대신 .query를 사용하여 내 게시물의 쿼리를 가져올 수있었습니다. 일단 내가 얻은 파일 이름을 파싱하는 가장 좋은 방법을 찾고 있었다. 그러나 이제는 주제에 관해서는 .query 또는 .value를 사용하는 것이 좋습니다. – Dusty

+1

'query()'는'XML' 데이터 유형의 인스턴스로 전체 XDM 결과 트리를 리턴합니다. 'value()'는 하나의 XDM 값만을 반환하도록 쿼리를 요구하고, 그것을 어떤 SQL 타입으로 변환합니다. 따라서 일반적으로 XML 문서 나 단편, 또는 적어도 노드 집합을 반환해야 할 때 전자를 사용하고, 노드 집합을 반환해야하는 경우에는 후자의 경우 단일 값을 반환해야 할 때 사용합니다. –

+0

감사합니다. 그건 의미가 있습니다. 그것이 당신에게 어떤 점수를주지는 않지만, 나는 당신의 의견을 upvoted. :) – Dusty

1

불행히도 SQL Server는 XQuery를 준수하지 않습니다. 오히려 상당히 제한된 XQuery 사양의 하위 집합입니다. fn:substring-before이 없을뿐만 아니라 또는 fn:string-to-codepoints을 직접 사용하여 fn:index-of을 수행 할 필요가 없습니다. 그래서, 제가 말할 수있는 한, 당신은 여기에 SQL이 붙어 있습니다.

+0

+1 감사합니다. SQL Server에 제한된 XQuery 하위 집합이있는 것이 두려웠습니다. 스티브 카스 (Steve Kass)가 생각한 것처럼 SQL Server에서 하위 문자열 기능을 사용해야 할 것 같습니다. – Dusty

4

이렇게하는 간단한 방법은 SUBSTRING 및 CHARINDEX입니다. (현명한 여부) 파일 이름의 첫 번째 부분의 길이를 변경하지 않는 것을 가정 할 때,하지만 여전히 파일 이름을 찾을 수 XQuery를 사용하려는, 여기에 짧은 생식 당신이 원하는 않는입니다 :이

declare @t table (
    parms varchar(max) 
); 
insert into @t values ('<xml filename="100100_456_484351864768.zip" event_dt="10/5/2009 11:42:52 AM"><info user="TestUser" /></xml>'); 

with T(fName) as (
    select cast(cast(parms as xml).query('data(/xml/@filename)') as varchar(100)) as p 
    from @t 
) 
    select 
    substring(fName,8,charindex('_',fName,8)-8) as myNum 
    from T; 

REPLACE 및 PARSENAME 또는 REVERSE와 같은 다른 문자열 함수를 사용하는 부적절한 솔루션이지만 더 효율적이거나 읽기 쉽지는 않습니다. 고려해야 할 한 가지 가능성은 정규 표현식 처리를 SQL로 가져 오는 CLR 루틴을 작성하는 것입니다.

그렇다면 xml이 항상 단순하다면 XQuery를 전혀 사용하지 않을 특별한 이유가 없습니다. 원하는 숫자를 추출 할 두 가지 쿼리가 있습니다.당신이 당신의 XML 문자열 또는 파일 이름의 첫 번째 부분의 길이가 변경 될 가능성을 통해 여분의 공백을 제어 할 수없는 경우 두 번째는 안전 :

select 
    substring(parms,23,charindex('_',parms,23)-23) as myNum 
    from @t; 

    select 
    substring(parms,charindex('_',parms)+1,charindex('_',parms,charindex('_',parms)+1)-charindex('_',parms)-1) as myNum 
    from @t; 
+0

+1 SQL Server 하위 문자열을 사용하여 구문 분석을 수행해야한다고 생각했던 작업을 수행해야합니다. 귀하의 답변에 감사 드리며 저에게 많은 도움을드립니다. 첫 번째 게시물과 비슷한 기능을 수행 할 것이라고 생각하지만이 상황에서는 게시 한 두 번째 코드 샘플이 작동하지만 문자열 조작을 수행하기 전에 XQuery를 사용하여 파일 이름을 추출합니다. 다시 한 번 도움을 주셔서 감사 드리며 답변으로 표시하겠습니다. – Dusty