>>Storing XML in Relational Databases (1)<< Storing XML in Relational Databases (1)From http://www.xml.comtranslating by bjcfremail:bjcfr@sohu.com引言有许多方法可以解决XML数据和关系数据库数据之间进行有效的相互转换的问题,数据库系统供应商如:IBM,微软,ORACLE,SYBASE等均开发了一些工具来帮助把XML文档转换成关系数据表,以下是几种不同的解决方案:1. ORACLE XML SQL UTILITY 把XML文档的诸多元素模拟成一些嵌套的表,相应的元素利用ORACLE OBJICT 数据类型来模拟。“SQL-TO-XML”的转换是通过数据表(referenced by Object datatype)和嵌套元素的一一对应关系来创建XML文档的。“XML-TO-SQL”的转换则需要对数据模型进行修改(把它从关系型转换为对象型)或者重建原始的XML文档。2. IBM DB2 XML 扩展允许把XML 文档作为类似于BLOB(二进制大对名象)的对象进行存储或把它们分解成一系列的表进行存储。后者的转换(known as XML collection)在XML 1.0的语法中被定义。3. 微软通过扩展SQL-92和引进OPENXML行集来解决这个问题。4. SYSBASE ADAPTIVE用SERVER 引进了JAVA 类ResultSetXml作为这种双向转换处理的基础。在本文中,我们为先分析一下这些供应商解决方案的细节,然后我们为试着加答下列问题:• 我们能否重新构造并简 个问题?• 在异构数据库环境下什么才是正确的解决方法?下面的DTD是本文的所使用的范例:<!-- Primitive Types --> <!ELEMENT CURRENCY1 (#PCDATA)><!ATTLIST CURRENCY1 e-dtype NMTOKEN #FIXED "string" e-dsize NMTOKEN #FIXED "3"> <!ELEMENT CURRENCY2 (#PCDATA)><!ATTLIST CURRENCY2 e-dtype NMTOKEN #FIXED "string" e-dsize NMTOKEN #FIXED "3"> <!ELEMENT AMOUNT (#PCDATA)><!ATTLIST AMOUNT e-dtype NMTOKEN #FIXED "decimal"> <!ELEMENT SETTLEMENT (#PCDATA)><!ATTLIST SETTLEMENT e-dtype NMTOKEN #FIXED "date"> <!ELEMENT BANKCODE (#PCDATA)><!ATTLIST BANKCODE e-dtype NMTOKEN #FIXED "string"> <!ELEMENT BANKACCT (#PCDATA)><!ATTLIST BANKACCT e-dtype NMTOKEN #FIXED "string"> <!-- Derived Types --> <!ELEMENT ACCOUNT (BANKCODE, BANKACCT)> <!ELEMENT FXTRADE (CURRENCY1, CURRENCY2, AMOUNT, SETTLEMENT, ACCOUNT)> Oracle XML-SQL Utility (XSU)SQL到XML的映射ORACLE 把一系列的对象引用从数据库转化为XML元素的层次结构。表FXTRADE中的字段ACCOUNT用来作为类型AccountType对象引用的模拟。 CREATE TABLE FXTRADE { CURRENCY1 CHAR (3), CURRENCY2 CHAR (3), AMOUNT NUMERIC (18,2), SETTLEMENT DATE, ACCOUNT AccountType // object reference} CREATE TYPE AccountType as OBJECT{ BANKCODE VARCHAR (100), BANKACCT VARCHAR (100) } 下面是从给定的对象-关系模型利用语句“SELECT * FROM FXTRADE”产生的相对应的XML文档:<?xml version="1.0"?><ROWSET> <ROW num="1"> <CURRENCY1>GBP</CURRENCY1> <CURRENCY2>JPY</CURRENCY2> <AMOUNT>10000</AMOUNT> <SETTLEMENT>20010325</SETTLEMENT> <ACCOUNT> <BANKCODE>812</BANKCODE> <BANKACCT>00365888</BANKACCT> </ACCOUNT> </ROW> <!-- additional rows ... --> </ROWSET> 从数据库中提取XML下面的例子取自于ORACLE’s XSU 文档,把相应的SQL语句进行的替换并使用ORACLE的纯JAVA JDBC 瘦驱动程序。首先,创建一个OracleXMLQuery的实例,然后执行一个查询,结果就是上面所提及的XML文档。相似地,XML文档也可以从DOM中被抽取,在这种情况下,应使用qry.getXMLDOM()而不是getXMLString().import oracle.jdbc.driver.*;import oracle.xml.sql.query.OracleXMLQuery;import java.lang.*;import java.sql.*; // class to test XML document generation as Stringclass testXMLSQL { public static void main(String[] args) { try { // Create the connection Connection conn = getConnection("scott","tiger"); // Create the query class OracleXMLQuery qry = new OracleXMLQuery(conn, "SELECT * FROM FXTRADE"); // Get the XML string String str = qry.getXMLString(); // Print the XML output System.out.println("The XML output is:\n"+str); // Always close the query to get rid of any resources.. qry.close(); } catch(SQLException e) { System.out.println(e.toString()); } } // Get the connection given the user name and password.! private static Connection getConnection(String username, String password) throws SQLException { // register the JDBC driver.. DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); // Create the connection using the OCI8 driver Connection conn = DriverManager.getConnection( "jdbc:oracle:thin:@dlsun489:1521:ORCL", username,password); return conn; }} Storing XML in the database在这个例子中,用OracleXMLSave来把我们的XML文档存储为一个对象-关系模型insertXML方法用于插入数据。import java.sql.*;import oracle.xml.sql.dml.OracleXMLSave;public class testXMLInsert{ public static void main(String args[]) throws SQLException { Connection conn = getConnection("scott","tiger"); OracleXMLSave sav = new OracleXMLSave(conn, "scott. FXTRADE"); // Assume that the user passes in this document as 0-arg sav.insertXML(args[0]); sav.close(); } ...} 如果XML和数据库中的关系对象模型是同步的,但是如果不同步呢?这种情况下,通常有两种选择:1. 调整关系对象模型,通过创建一个可更改的关系对象视图和完成多表的修改。2. 可以把XML文档分解成一系列的简单的子文档。我们可以利用XSLT来过完成这个分解过程。XSU不允许存储属性值,建议先把属性转换成元素再作处理。Oracle XSU总结一个XML到SQL的映射可以被一个关系对象模型进行模拟,其创建规则如下:每一个嵌套的XML元素被映射为一个适当的对象引用。映射的规则已经内嵌在数据库模型上了。相关的JAVA API包括OracleXMLQuery和 OracleXMLSave 两个类。(未待续完)