【问题标题】:Search XML files stored in a MS SQL database搜索存储在 MS SQL 数据库中的 XML 文件
【发布时间】:2017-01-31 05:08:04
【问题描述】:

我有超过 500,000 个 XML 文件存储在一个 MS SQL 数据库中,例如下面的一个(为了节省问题的空间而对其进行了编辑)。

    <?xml version="1.0"?>
    <PROJECTS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <row>
    <APPLICATION_ID>7000518</APPLICATION_ID>
    <ACTIVITY>C06</ACTIVITY>
    <ADMINISTERING_IC>RR</ADMINISTERING_IC>
    <APPLICATION_TYPE>1</APPLICATION_TYPE>
    <BUDGET_START>09/01/2009</BUDGET_START>
    <BUDGET_END>09/30/2013</BUDGET_END>
    <FULL_PROJECT_NUM>1C06RR020539-01A1</FULL_PROJECT_NUM>
    <FY>2009</FY>
    <ORG_STATE>CA</ORG_STATE>
    <ORG_ZIPCODE>900952000</ORG_ZIPCODE>
    <PIS>
    <PI>
    <PI_NAME>JONES,MARY</PI_NAME>
    <PI_ID>9876543</PI_ID>
    </PI>
    <PI>
    <PI_NAME>DOE, JOHN</PI_NAME>
    <PI_ID>1234567</PI_ID>
    </PI>
    </PIS>
    <PROJECT_TERMSX>
    <TERM>Extramural Activities</TERM>
    <TERM>Extramural Research Facilities Construction Project</TERM>
    </PROJECT_TERMSX>
    <PROJECT_TITLE>The Center for Oral/Research</PROJECT_TITLE>
    <SUPPORT_YEAR>1</SUPPORT_YEAR>
    </row>
   </PROJECTS>

我可以使用以下方式搜索任何单个节点:

    SELECT   nref.value('(APPLICATION_ID)[1]', 'Int')    APPLICATION_ID,
    nref.value('(ACTIVITY)[1]', 'varchar(3)') ACTIVITY
    FROM [XML_2010] cross apply XMLData.nodes('//PROJECTS/row') as R(nref)
    WHERE  nref.value('(CORE_PROJECT_NUM)[1]', 'varchar(25)') LIKE '%CA187342%'

但是我如何才能找到与所有将 DOE、JOHN 作为 PI(PIS 的子节点)的 XML 文件关联的数据?比如APPLICATION_ID和BUDGET_START等? 感谢您的帮助

【问题讨论】:

  • 所有 XML 的结构都相同吗?您的代码看起来像是在使用 real XML 数据类型,但您的示例以 &lt;?xml version="1.0"?&gt;?这是存储为字符串(哪个列数据类型?)还是从文件中读取?您是否一直在寻找相同的信息进行过滤,或者您可能需要来自内部的任何信息?乍一看,我建议在索引侧列中写入一些值。也许把全部写到一张普通的桌子上?
  • 所有的 XML 文件都是相同的结构。数据类型为 XML。我将获得的包含大约 100K 记录的 XML 数据文件解析为单独的文件。如果有更好的方法,我愿意接受建议。我应该将所有内容解析为普通表吗?我希望它找到与 PI 关联的记录,然后将它们解析成表格。我不需要所有 100K 记录,但直到我搜索才知道哪些记录

标签: sql-server xml


【解决方案1】:

XML 非常适合存档和数据交换,但它是存储主动使用/过滤/搜索数据的错误容器。因此,我强烈建议您将所有数据传输到经典的索引表中,如下所示:

注意我将您的 XML 简化为每个级别的一些示例,其余的遵循相同的方法,由您决定。声明的表变量是为了模拟一个测试场景:

DECLARE @YourTable TABLE(ID INT IDENTITY,YourXml XML);
INSERT INTO @YourTable VALUES
('<PROJECTS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <row>
    <APPLICATION_ID>7000518</APPLICATION_ID>
    <ACTIVITY>C06</ACTIVITY>
    <!-- more first level elements like above -->

    <!-- Here there are multiple PIs -->
    <PIS>
      <PI>
        <PI_NAME>JONES,MARY</PI_NAME>
        <PI_ID>9876543</PI_ID>
      </PI>
      <PI>
        <PI_NAME>DOE, JOHN</PI_NAME>
        <PI_ID>1234567</PI_ID>
      </PI>
    </PIS>

    <!-- Here there are multiple PROJECT_TERMS -->
    <PROJECT_TERMSX>
      <TERM>Extramural Activities</TERM>
      <TERM>Extramural Research Facilities Construction Project</TERM>
    </PROJECT_TERMSX>


    <!-- These are normal first level elements again -->
    <PROJECT_TITLE>The Center for Oral/Research</PROJECT_TITLE>
    <SUPPORT_YEAR>1</SUPPORT_YEAR>
  </row>
</PROJECTS>');

--这个SELECT将所有一级数据连同部分XML一起读入一个临时表#Projects

SELECT r.value('(APPLICATION_ID/text())[1]','bigint') AS APPLICATION_ID
      ,r.value('(ACTIVITY/text())[1]','nvarchar(max)') AS ACTIVITY
      --more columns like above
      ,r.query('PIS') AS AllPis
      ,r.query('PROJECT_TERMSX') AS AllProjectTerms
      --more first level columns
INTO #Projects
FROM @YourTable AS t
OUTER APPLY t.YourXml.nodes('/PROJECTS/row') AS A(r);

--这个SELECT#Projects 读取并将所有相关的PI-data 存储在另一个临时表#PIs

SELECT APPLICATION_ID
      ,p.value('(PI_ID/text())[1]','bigint') AS PI_ID
      ,p.value('(PI_NAME/text())[1]','nvarchar(max)') AS PI_NAME
INTO #PIs
FROM #Projects AS p
OUTER APPLY p.AllPis.nodes('PIS/PI') AS A(p); 

--同#Terms

SELECT APPLICATION_ID
      ,t.value('(./text())[1]','nvarchar(max)') AS TERM
INTO #Terms
FROM #Projects AS p
OUTER APPLY p.AllProjectTerms.nodes('PROJECT_TERMSX/TERM') AS A(t); 

--这是你的临时表的内容

SELECT * FROM #Projects;
SELECT * FROM #PIs;
SELECT * FROM #Terms;

--Clean up
GO
DROP TABLE #Projects;
DROP TABLE #PIs;
DROP TABLE #Terms;

Clean up 之前,您将输入一些代码,它将您的数据从这些暂存表中写入真实表中。定义关系的 ID 与数据一起存储。这应该很容易。您将需要INSERT INTOMERGE,具体取决于您是否必须处理现有数据。

提示

您可能会想到projects and PIsprojects and terms 之间的m:n 关系。为此,您将编写一个单独的 PI 表和一个单独的 Term-table,其间有一个映射表(保存 application_id 和第二个 id,都作为外键)

【讨论】:

    猜你喜欢
    • 2010-11-11
    • 2015-03-13
    • 2017-09-09
    • 2019-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    • 1970-01-01
    相关资源
    最近更新 更多