软件频道>程序开发>JavaVBVCDelphiC/C++Web开发微软专栏移动数据库程序人生软件工程|开发客
您现在的位置: 天极网 > 开发频道 > DB2 的 pureXML 特性与 Ruby on Rails
全文

DB2 的 pureXML 特性与 Ruby on Rails

2007-12-13 10:36作者:John Chun出处:论坛整理责任编辑:方舟
  既然已经通过迁移实现了所有必需的模式修改,就可以将 XML 数据上载到 XML_CONTENTS 表中。将多个 XML 文档插入表中最容易的方法是使用 DB2 9 数据服务器中的 IMPORT 实用程序。IMPORT 实用程序允许导入格式良好的 XML 文档,可以同时进行 XML 模式检验,也可以不检验。对于我们当前的使用情况,需要确保正确地更新 XML_CONTENTS 表、DOCUMENTS 表和 SUBJECTS 表中的相关条目。因此,应该使用生成的 scaffold 每次上载一个文件,从而维护所有外键关联。

  在图 2 中可以看到,新文档视图 /app/views/documents/new.rhtml 显示创建了一个与 XML 内容相关联的新文档,还创建了与新文档相关联的新主题。

  图 2. 将 XML 文档上载到 Team Room 存储库中

  上载新的 XML 文档

  现在应该上载其他 XML 文档,这些文档包含加拿大和美国一些地区的模拟市场营销数据,后面将用这些文档运行 XQuery 和 XPath 搜索。这些 XML 文件放在 /test/fixtures 目录中,这里还放着用于文档检验的 marketinfo.xsd XML 模式。在本文末尾的 下载 中可以找到更新后的 Team Room 应用程序。

  XML 数据类型的基本 CRUD 操作

  我们来执行一些基本的 XML 创建、获取、更新和删除(CRUD)操作,体会一下如何管理 XML 数据。

  为了演示这些操作,假设市场营销部门希望调查客户生活的城市。在这些城市中将发起一次有针对性的市场营销活动,从而提高品牌知名度和客户光顾次数。为此,我们可以从 XML_CONTENTS 表中存储的市场营销信息 XML 文档中提取出数据。另外,我们决定存储产生的调查报告,以便记录不断增加的城市信息库。如果决定以 XML 格式创建城市数据库,那么不需要创建另一个表来跟踪这些数据。我们只需用这些数据组成一个 XML 文档,然后将它作为 XML 插入同一列中。以后的某个时候,DBA 可能希望创建一个新的表来分隔应用程序数据,但这仅仅是一个逻辑和语义需求,不是数据库的要求。

  在 DB2 中,可以以多种方式查询 XML 数据:使用 SQL、XQuery 或这两者的组合。这个示例使用 XQuery。使用 XQuery 有助于用查询结果构造 XML 文档。清单 11 给出要执行的 XQuery:

  清单 11. 城市调查 XQuery

 XQUERY
<cities>
   declare default element namespace "http://www.ibm.com/developerworks";
   { for $c in fn:distinct-values(
         db2-fn:xmlcolumn(
        'XML_CONTENTS.DATA')/marketinfo/sales/customer/address/city)
         order by $c
      return <city>{$c}</city>
   }
</cities>

  首先看看函数 db2-fn:xmlcolumn() 中的语句,然后向外依次解释,这样才能理解这个 XQuery 的工作方式。db2-fn:xmlcolumn() 函数从当前连接的 DB2 数据库中的 XML 列获取一个序列。在这里,我们要从 XML_CONTENTS 表的 DATA 列获取数据。但是,我们不需要所有数据,只需要 XPath 表达式指定的子集:/marketinfo/sales/customer/address/city。

  换句话说,我们希望查看表中每一行中的所有 XML 文档,并选择 XPath 中出现的所有 city 元素。这会造成一个潜在的问题,因为多个客户可能住在同一城市。为了处理这个问题,我们使用 XQuery 函数 fn:distinct-values()。顾名思义,它将返回一系列不同的 city 元素,城市名不会重复。这个序列被赋值给变量 $c。

  在最后一步之前,对 $c 中的城市进行排序。然后返回结果。XQuery 的强大特性之一是,返回数据的格式是可以充分定制的。因为我们当前已经获得了一系列城市名称,所以将每个城市封装在一个 元素中。这是一系列元素,还不是有效的 XML 文档,因为它没有根元素。为了确保返回有效的 XML 文档,将整个结果放在一个 元素中,所以数据现在像清单 12 这样(按照升序)。

  清单 12. 返回的典型 XML 数据

 <cities>
  <city>Atlanta</city>
  <city>Augusta</city>
  <city>Austin</city>
  <city>Baton Rouge</city>
  <city> ... </city>
</cities>

  要想了解 DB2 9 中的 XQuery 的更多信息,请参考 DB2 XML Guide(本文末尾的 参考资料 一节中提供了有关链接)。

  现在已经获得了 XML 文档形式的城市列表,我们要将这个文档插入数据库中。开发人员可以按照与插入任何数据类型相同的方式将 XML 文档插入数据库中。

  清单 13. 插入 XML 文档

class DocumentsController < ApplicationController
  [...]
  def upload
  [...]
      @document = Document.new(params[:document])
      @subject = params[:subject_name] && params[:subject_name].empty? ?
                 Subject.new :
                 Subject.find_by_name(params[:subject_name])

      Document.transaction do
        User.find(session[:user_id]).documents << @document
        @subject.documents << @document
        @subject.size = @subject.documents.size
        if @subject.new_record?
          @subject.name        = params[:subject][:name]
          @subject.tag         = params[:subject][:tag]
          @subject.description = params[:subject][:description]
          @subject.save
        end
 
        if @document.save
          flash[:notice] = "Document #{@document.name} successfully created."
  [...]
end 

  因为在任何给定的时刻客户的数量都不是静态的,所以我们希望定期更新客户城市的列表,比如每周一次或每月一次,从而保证这个列表反映最新情况。为此,可以执行相同的 XQuery 语句。数据库中当前的文档会被替换为 XML 文件的最新版本,因为它的 id 是相同的。注意,有一个传递给编辑视图表单(/app/views/documents/_form.rhtml)的隐藏的 :id 参数,在 DocumentsController 中使用这个参数获取现有的文档:

  清单 14. 更新 XML 文档

 class DocumentsController < ApplicationController
  [...]
  def update
    @document = Document.find(params[:document][:id])
    if @document.update_attributes(params[:document])
      flash[:notice] = 'Document was successfully updated.'
      redirect_to :action => 'show', :id => @document
    else
      render :action => 'edit'
    end
  end
  [...]
end

  在内部,DB2 重新分配现有的 XML 数据页面并插入新的值。所以实际效果就是用新的更新后的文档替换整个 XML 文档。

  最后,当数据不再有用时,或者数据可以由其他机制处理时,就需要删除数据。例如,DBA 可能希望把不同的信息隔离开,比如使用另一个表中的另一个 XML 列。为了删除文档,需要执行 DELETE 语句,并加上适当的 WHERE 谓词。在 Ruby 中,可以这样做:

  清单 15. 删除 XML 文档

class DocumentsController < ApplicationController
  [...]
  def destroy
    Document.find(params[:id]).destroy
    redirect_to :action => 'list'
  end
end

相关搜索:
关注此文读者还看过
热门关注
特别推荐
文章排行
本周
本月
最近更新
关于我们|About us|网站律师|天极服务|电子杂志|RSS订阅|加入我们|网站地图
TMG
Copyright (C) 1999-2009 Chinabyte.com, All Rights Reserved 版权所有 天极网络
商务联系、网站内容、合作建议:010-82657868
版权声明 在线提交意见反馈 渝ICP证B2-20030003号
经营性网站备案信息 网警备案 中国网站排名
天极传媒:天极网|比特网|IT专家网|IT商网|52PK游戏网|IT分众