2014-01-15 5 views
2

나는 조정해야하는 보고서 스펙 하위 시스템을 상속 받았습니다. 임무는 tReports 테이블에 날짜 열을 추가하고 XML 코드 스펙에 포함 된 (예정되어있는) CreateDate로 채 웁니다. 문제는 일부 이전 보고서에는 CREATEDATE 특성이 없거나 아래 예와 같이 XML이 유효하지만 잘못 형성되어 있으며 대부분의 다른 보고서에서 작동하는 xQuery를 사용하여 CREATEDATE를 검색 할 수 없다는 것입니다. 명시 적으로 작성 날짜가 스펙에 포함되어 있지 않기 때문에 합리적인 날짜를 예상하기 위해 보간을 사용하고 있습니다. 보간법의 한 가지 요인은 보고서 스펙에 포함 된 날짜 문자열을 보는 것입니다. 일부는 유용 할 것이고 다른 것은 유용하지 않을 수 있습니다.단일 varchar (MAX) 열에서 여러 날짜 문자열 추출 SQL Server

날짜 문자열에 대한 각 보고서 스펙을 시각적으로보고 싶지 않은 보고서가 너무 많습니다 (1,200 이상). 이 날짜 문자열은 보고서 스펙의 모든 위치에 나타날 수 있으며 날짜 문자열을 포함 할 수있는 매우 많은 수의 요소와 속성 조합이 있습니다.

이상적인 솔루션은 reportID와 날짜 문자열을 UPDATE에서 사용할 준비가되었지만 날짜 형식이 다양하기 때문입니다 (m/d/yy, mm/dd/yy, m/dd/yy .. .) 나중에 정리할 수있는 날짜 문자열을 둘러싼 가짜 문자를 얻는 것에 감사 드려요.

모든 날짜 문자열은 2000 이상이므로 I'v에서 사용한 검색 문자열은 '/ 20'이며 좋은 결과를 제공합니다.

저는 이런 종류의 문제에 관해 논의한 여러 사이트를 살펴본 결과, Mikael Eriksson이 설명하는 것과 같은 해결책을 찾았지만 몇 시간의 게임 후에는 작동하지 않을 수 있습니다. 그것. How to extract multiple strings from single rows in SQL Server

커서 나 WHILE 루프를 사용하지 않고 이러한 포함 된 날짜를 추출하는 방법이 있습니까?

-- Some representative data: (I'm using SQL Server 2008 R2) 
CREATE TABLE #ReportSpecs (ReportID INT, ReportSpec VARCHAR(MAX)) 
INSERT INTO #ReportSpecs 
     (ReportID, ReportSpec) 
VALUES 
(136,   
'<ReportID>136</ReportID> 
<EmpIDCreator>23816</EmpIDCreator> 
<EmpName>Blanc, Melvin J</EmpName> 
<ReportType>0</ReportType> 
<ReportName>PSST Sys Spec</ReportName> 
<ReportData> 
    <REPORT> 
     <COLUMNS> 
     <Column Name="JobNumber" Position="1" /> 
     <Column Name="TaskType" Position="2" /> 
     <Column Name="Assignees" Position="3" /> 
     <Column NAME="JobDueDate" Position="4" /> 
     <Column Name="ReferenceNumber" Position="5" /> 
     <Column Name="Deliverable" Position="6" /> 
     <Column Name="Priority" Position="7" /> 
     </COLUMNS> 
     <FILTERS> 
     <FILTER NAME="TYPE" VALUE="To_Me" /> 
     <FILTER NAME="Status" VALUE="All" /> 
     <FILTER NAME="DateOptions" VALUE="DateRange" From="8/16/2002" To="8/23/2002" /> 
     <FILTER NAME="FromDate" VALUE="8/16/2002" /> 
     <FILTER NAME="ToDate" VALUE="8/23/2002" /> 
     <FILTER NAME="Role" VALUE="All" /> 
     </FILTERS> 
     <parameters> 
     <PARAMETER NAME="@Cascading" TYPE="integer" VALUE="0" /> 
     <PARAMETER NAME="@EmpID" SYSTEM="true" TYPE="integer" VALUE="#Request.EmployeeIDAlias#" /> 
     <PARAMETER NAME="@FromOrgs" TYPE="varchar(250)" VALUE="" /> 
     <PARAMETER NAME="@ToOrgs" TYPE="varchar(250)" VALUE="" /> 
     </parameters> 
     <NAME>PSST Sys Spec</NAME> 
     <OWNER> 
     <ID>23816</ID> 
     </OWNER> 
     <source id="8" useinternalid="True" /> 
    </REPORT> 
</ReportData>'), 

(311, 
'<ReportID>311</ReportID> 
<EmpIDCreator>7162</EmpIDCreator> 
<EmpName>Potter, Harry J</EmpName> 
<ReportType>0</ReportType> 
<ReportName>CPVC Synch Test</ReportName> 
<ReportData> 
    <REPORT> 
     <COLUMNS> 
     <Column Name="JobNumber" Position="1" /> 
     <Column Name="TaskType" Position="2" /> 
     <Column Name="Subject" Position="3" /> 
     <Column Name="CurrentAssignee" Position="4" /> 
     <Column NAME="JobDueDate" Position="5" /> 
     <Column Name="Deliverable" Position="6" /> 
     <Column Name="Category" Position="7" /> 
     <Column Name="Priority" Position="8" /> 
     </COLUMNS> 
     <FILTERS> 
     <FILTER NAME="TYPE" VALUE="By_Orgs_6098,By_Orgs_6123" /> 
     <FILTER NAME="Status" VALUE="Open" /> 
     <FILTER NAME="DateOptions" VALUE="DateRange" From="3/25/2002" To="4/4/2002" /> 
     <FILTER NAME="ReviewFromDate" VALUE="3/25/2002" /> 
     <FILTER NAME="ReviewToDate" VALUE="4/4/2002" /> 
     <FILTER NAME="Role" VALUE="All" /> 
     </FILTERS> 
     <parameters> 
     <PARAMETER NAME="@Act" TYPE="integer" VALUE="0" /> 
     <PARAMETER NAME="@MgrID" SYSTEM="true" TYPE="integer" VALUE="#Request.EmployeeIDAlias#" /> 
     <PARAMETER NAME="@MgrIDActing" TYPE="integer" VALUE="" /> 
     <PARAMETER NAME="@FromDept" TYPE="varchar(250)" VALUE="" /> 
     <PARAMETER NAME="@FromEmp" TYPE="varchar(250)" VALUE="" /> 
     <PARAMETER NAME="@ToDept" TYPE="varchar(250)" VALUE="" /> 
     </parameters> 
     <NAME>CPVC Synch Test</NAME> 
     <OWNER> 
     <ID>7162</ID> 
     </OWNER> 
     <source id="17" useinternalid="True" /> 
    </REPORT> 
</ReportData>'), 

(1131, 
'<ReportID>1131</ReportID> 
<EmpIDCreator>13185</EmpIDCreator> 
<EmpName>Reed, Alan</EmpName> 
<ReportType>0</ReportType> 
<ReportName> 
    ''"><script>alert(''hello'')</script> 
</ReportName> 
<ReportData> 
    <Report NAME="''"> 
     <script>alert(''hello'')</script>" CREATEDATE="12/7/2009"> 
     <DESCRIPTION>sfasf</DESCRIPTION> 
     <OWNER ID="13185"/> 
     <SOURCE ID="1" USEINTERNALID="TRUE"/> 
     <COLUMNS> 
     <COLUMN NAME="JobNumber" POSITION="1" SORTORDER="asc"/> 
     </COLUMNS> 
     <FILTERS> 
     <FILTER NAME="TYPE" VALUE="By_Me,To_Me" /> 
     <FILTER NAME="ASGSTATUS" VALUE="Open" /> 
     <FILTER NAME="DATEOPTIONS" VALUE="All" /> 
     <FILTER NAME="STATUS" VALUE="Open" /> 
     <FILTER NAME="ASGDATEOPTIONS" VALUE="All" /> 
     <FILTER NAME="ROLE" VALUE="All" /> 
     </FILTERS> 
     <PARAMETERS> 
     <PARAMETER NAME="@Me" TYPE="integer" VALUE="3" /> 
     <PARAMETER NAME="@FromCost" TYPE="varchar(250)" VALUE=""/> 
     <PARAMETER NAME="@ToCost" TYPE="varchar(250)" VALUE="" /> 
     </PARAMETERS> 
     <ADVANCEDSORT SortByA="JobNumber" SortOrderA="asc" SortByB="" SortOrderB="" SortByC="" SortOrderC="" /> 
    </Report> 
</ReportData>'); 

/* 
Desired Output (A DISTINCT list would be better, but just getting this output would be GREAT.) 
ReportID DateString 
-------- ---------- 
    136 8/16/2002 
    136 8/23/2002 
    136 8/16/2002 
    136 8/23/2002 
    311 3/25/2002 
    311 4/4/2002 
    311 3/25/2002 
    311 4/4/2002 
    1131 12/7/2009 
*/ 

DROP TABLE #ReportSpecs 

감사합니다.

답변

0
select R.ReportID, 
     D.V as DateString 
from #ReportSpecs as R 
    cross apply (select cast(R.ReportSpec as xml)) as X(R) 
    cross apply X.R.nodes('//@*, //*/text()') as T(X) 
    cross apply (select T.X.value('.', 'varchar(max)')) as D(V) 
where charindex('/20', D.V) > 0 

결과 :

ReportID DateString 
----------- -------------------------- 
136   8/16/2002 
136   8/23/2002 
136   8/16/2002 
136   8/23/2002 
311   3/25/2002 
311   4/4/2002 
311   3/25/2002 
311   4/4/2002 
1131  " CREATEDATE="12/7/2009"> 
+0

이 뛰어난 작품, 미카엘, 감사합니다. 몇 가지 사소한 수정과 함께, 첫 번째 버전은 1,600 건에서 468 건으로 목록을 무너 뜨 렸습니다. 위에 표시된 보고서 1131 에서처럼 "까다로운"날짜가있는 166 개의 보고서가이 편집 된 버전으로 식별되었습니다. XML은 유효하지 않으며 (일반적으로 내장 SQL로 인해) "CAST as XML"에 실패하기 때문에 나머지 302 개는 텍스트 검색 기준으로 접근해야합니다. 다시 한번 감사드립니다. –

관련 문제