从单个varchar(MAX)列SQL Server中提取多个日期字符串

时间:2014-01-15 14:07:19

标签: sql sql-server string date

我继承了需要调整的报告规范子系统。任务是在tReports表中添加一个日期列,并使用XML代码规范中包含的(应该是)CreateDate填充它。问题是某些较旧的报告没有CREATEDATE属性,或者在下面的一个示例中,XML有效但形成不良,并且无法使用适用于大多数其他报告的xQuery检索CREATEDATE。由于我没有在规范中包含明确的创建日期,我使用插值来估计合理的日期。插值的一个因素是查看报告规范中包含的日期字符串 - 一些将是有用的,另一些则不是。

有太多报告(超过1,200个)可视化地浏览日期字符串的每个报告规范。这些日期字符串可以出现在报表规范中的任何位置,并且可以包含日期字符串的元素和属性的组合非常多。

理想的解决方案是reportID的列表和准备在UPDATE中使用的日期字符串,但因为日期格式不同(m / d / yy,mm / dd / yy,m / dd / yy ......我很感激能够在日期字符串周围找到一个虚假的字符,以后我可以清理它。

所有日期字符串都是2000或更高版本,因此我使用的搜索字符串是'/ 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

感谢您的时间。

1 个答案:

答案 0 :(得分:1)

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">