Products Connect for JDBC Connect for ODBC Connect64 for ODBC Connect for .NET Connect for ADO Connect for SQL/XML DataDirect XQuery SequeLink Downloads Evaluations Support Getting Started Product Information Downloads Troubleshooting Forums OEM Resources Evaluation Help About SupportLink Site Map Developer Forums Code Library JDBC ODBC .NET XML Design Preview OEM Login OEM/ Channel Partner Channel Partners OEM Case Studies Company History Strategic Relationships Management Team Careers News Events |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Topics Basics Definitions Useful Links Topics Basics Definitions Useful Links Topics Basics Definitions Useful Links Topics Basics Definitions Useful Links |
|
Introduction | ||
This document explores different
approaches for creating XML structures from SQL queries by
comparing SQL/XML to custom-coded solutions using JDBC and
SAX or DOM and to proprietary XML extensions from the
database vendors. Many Java applications exchange data as
XML, but store and query data using a JDBC connection to a
traditional relational database. Unfortunately, XML and SQL
represent information in very different ways, and many
developers spend significant effort converting between the
two formats. When producing XML for exchange, developers
need a way to build hierarchical XML structures using
queries on a set of unordered, two-dimensional tables.
Similarly, they need a way to update the content of their
two dimensional tables using data found in XML
hierarchies. SQL/XML, part of the SQL
2003 standard, is an extension to the SQL standard that
allows XML to be generated as the result of a query, and
adds an XML data type to SQL so that XML query results can
be returned in the columns of normal SQL result sets. Using standard SQL/XML instead of
custom-coded solutions or proprietary vendor extensions
greatly simplifies development, provides for more
maintainable code, and allows portability across
databases. After introducing SQL/XML, we take
a simple usage scenario and show how a Java program might
generate XML from a relational database. We provide code
examples to compare the following solutions:
We show that the first two
solutions in the preceding list are portable across
operating systems and database vendors, but the SQL/XML
solution requires much less code, is more efficient, and is
easier to write and maintain than building XML using DOM
and SQL queries. We show that the last three solutions,
which rely on proprietary extensions from the database
vendors, are not only non-portable, but are also harder to
learn and more complex to use than Java applications that
use SQL/XML and a JDBC connection. |
||
Table of
Contents |
||
SQL/XML: SQL Queries that Create XML SQL/XML, DOM+JDBC, and Proprietary Database Extensions |
||
SQL/XML: SQL Queries that Create XML | ||
In many environments, the vast
majority of important data is stored in relational
databases, but the majority of data exchange is done
using XML, which is used to provide data for exchange as
web messages or for display on web sites. Making
relational data ready for data exchange typically
involves a significant amount of work, because data in
relational databases is represented as distinct
two-dimensional tables that must be joined together to
create different representations of the same information.
Data in XML is represented using only hierarchy and
sequence - two relationships that do not exist in
traditional relational databases. The developer is forced
into the role of restructuring and translating between
two very different worlds. Because the same information
may be restructured in a variety of ways to create many
different XML documents, developers often spend a great
deal of time performing this one task.
For example, consider the
following relational tables: So that the information in these tables can easily be displayed on a web site or exchanged in web messages, we need to convert it to XML. In most applications, the XML that is displayed or exchanged is the result of some query. For example, here's an XML document that lists the projects for each customer - it was created by joining these two tables and creating a hierarchical XML structure to contain the following result: <?xml version="1.0" encoding="UTF-8"?> <customers> <customer id="1"> <name>Woodworks</name><city>Baltimore</city> <projects> <project id="1"><name>Medusa</name></project> </projects> </customer> ... <customer id="4"> <name>Hardware Heaven</name><city>Washington</city> <projects> <project id="2"><name>Pegasus</name></project> <project id="8"><name>Typhoon</name></project> </projects> </customer> ... </customers> Applications typically use SQL
queries to generate the information needed to build an
XML document. Most applications devote significant effort
to converting between relational data and XML documents
because of their different representations. Because the
information from a database can be displayed in many
different ways on web pages or in web messages, many
companies want a standard and efficient way to create XML
as the result of SQL queries. The first popular commercial
solutions to this problem came from the relational
database vendors, for whom XML support has been an
important competitive feature. Almost all major RDBMS
vendors now supply tools or product enhancements to help
bridge the gap between XML and relational data. Building
on their experience, the database vendors initiated an
action within the ANSI/ISO SQL standard to provide XML
support as part of SQL 2003. SQL/XML [8] provides XML
functions that allow SQL queries to create XML structures
and specifies how SQL tables, schemas, catalogs, data
types, values, character sets, and names are translated
to and from XML. SQL/XML also introduces a new data type,
the XML data type. In the first half of this
document, we present SQL/XML's XML mapping and the five
XML functions used to create XML structures. The second
half of this paper shows a SQL/XML query and the code
needed to implement the same SQL99 query together with
the DOM, and with the proprietary XML extensions for
Microsoft SQL Server, IBM DB2, and Oracle. We will show
that using standard SQL/XML instead of proprietary vendor
extensions greatly simplifies development, provides for
more maintainable code, and allows portability across
databases. Mapping a SQL Table to an XML
Document SQL/XML queries create XML from
relational data, and the standard specifies exactly how
SQL tables, schemas, catalogs, data types, values,
character sets, and names are translated to and from XML.
This specification is quite detailed, but the results are
intuitive and easily grasped by looking at an example.
Consider the Customers table: Here's an XML document that corresponds to the preceding table using the default SQL/XML mappings: <Customers> <row> <CustId>1</CustId> <Name>Woodworks</Name> <City>Baltimore</City> </row> <row> <CustId>2</CustId> <Name>Software Solutions</Name> <City>Boston</City> </row> <row> <CustId>3</CustId> <Name>Food Fantasies</Name> <City>New York</City> </row> ... </Customers> You can use SQL/XML functions to
create XML results in the SELECT clause of a SQL
statement. XMLELEMENT -
XMLATTRIBUTES The XMLELEMENT and XMLATTRIBUTES
functions are used to create XML elements and XML
attributes. The following example demonstrates how to
create a hierarchical XML structure with XML elements and
attributes based on data from the Customers
table: SELECT c.CustId, XMLELEMENT(NAME "customer", XMLATTRIBUTES(c.CustId AS "id"), XMLELEMENT(NAME "name",c.Name), XMLELEMENT(NAME "city",c.City)) AS "CustInfo" FROM Customers c The result set that is created contains two columns: the first column contains an integer value (CustId), the second column contains the result of the SQL/XML expression, which is a value whose data type is XML. XMLFOREST The XMLFOREST function creates a
list of XML values from a list of SQL values using
SQL/XML mappings. Here's a query that uses XMLFOREST to
create XML data: SELECT XMLFOREST(c.CustId AS "id",c.Name,c.City) FROM Customers c Here's the result of the preceding query: XMLFOREST is simple to use because it uses default mappings and does not force the user to specify how XML structures are created; however, it does not allow the user as much choice when compared to the functions that explicitly create XML structures, such as XMLELEMENT. It can be combined with other functions, such as XMLELEMENT, and elements can be renamed by using the SQL "AS" clause to rename a SQL column before the mapping is applied, as shown in the following query: SELECT c.CustId, XMLELEMENT(NAME "customer", XMLFOREST(c.CustId AS "id", c.Name AS "name", c.City AS "city") ) FROM Customers cHere's the result of the preceding query: XMLAGG The XMLAGG function often is used
to create child elements within a parent element using a
nested query. It concatenates all XML values that are
returned from a collection, such as a nested query, and
returns a single XML value. For example, in the following
query, the parameter for the last XMLELEMENT function
must be a single XML value: SELECT c.CustId, XMLELEMENT(NAME "customer", XMLATTRIBUTES(c.CustId AS "id"), XMLELEMENT(NAME "name",c.Name), XMLELEMENT(NAME "city",c.City), XMLELEMENT(NAME "projects", (SELECT XMLAGG(XMLELEMENT(NAME "project", XMLATTRIBUTES(p.ProjId AS "id"), XMLELEMENT(NAME "name",p.Name))) FROM Projects p WHERE p.CustId=c.CustId))) AS "customer-projects" FROM Customers cIn this example, the XMLAGG function concatenates (aggregates) all project information from the nested query into one XML value, which lists all the projects for a given customer. This XML value becomes the content of the element named projects. XMLCONCAT In SQL, the distinction between a
single value and a list of values is meaningful, so
SQL/XML must be able to distinguish a single XML value
with multiple XML elements from a list of XML values that
each contain one XML element. For example, in a SELECT
clause, each value of a tuple is represented in a column
of the result. Here's a query that creates a
list of XML values in the SELECT clause: SELECT c.CustId, XMLELEMENT(NAME "id",c.CustId), XMLELEMENT(NAME "name",c.Name), XMLELEMENT(NAME "city",c.City) FROM Customers cHere's the result of the preceding query: The XMLCONCAT function allows the three XML elements to be concatenated into one value, so that they all appear in the same column. Here's a query that concatenates the three XML elements into a column named CustInfo: SELECT c.CustId, XMLCONCAT( XMLELEMENT(NAME "id",c.CustId), XMLELEMENT(NAME "name",c.Name), XMLELEMENT(NAME "city",c.City)) AS "CustInfo" FROM Customers cIn the following result set, you can see that the second column, CustInfo, contains the concatenation of the three XMLELEMENT expressions: Using SQL/XML with JDBC is
similar to using SQL with JDBC, except that the result
set can contain instances of the XML data type. JDBC 3.0
does not support the XML data type; it is expected that
JDBC 4.0 will support it. In the meantime, JDBC-based
implementations that allow SQL/XML queries must provide
their own XML data type to retrieve XML
results. The following JDBC example
retrieves a result set using a SQL/XML query and extracts
the XML values from the result set: ... String sqlStr= new String ("SELECT c.CustId,xmlelement(NAME ....\n")); Statement stat=con.createStatement(); ResultSet rs=stat.executeQuery(sqlStr); while(rs.next()) { int id=rs.getInt(1); com.ddtek.jdbc.jxtr.XMLType xmlC= (com.ddtek.jdbc.jxtr.XMLType)rs.getObject(2); org.w3c.dom.Document doc=xmlC.getDOM(); ... } ...DataDirect Connect for SQL/XML DataDirect Connect for SQL/XML is a cross-platform
implementation of SQL/XML. It lets Java applications
return XML values in the columns of JDBC result sets and
access XML columns as JDOM, SAX, DOM, or text. It allows
you to write applications that work without change for
any major database including Oracle, DB2, SQL Server,
Informix, and Sybase. Currently, the SQL/XML standard
supports queries, but not updates. DataDirect
Technologies is a member of the H2.3 Task Group, which is
responsible for SQL/XML, and we hope that updates will be
added to the standard. In the meantime, Connect
for SQL/XML provides
proprietary extensions to the SQL99 Insert, Update, and
Delete statements that allow you to update data stored in
relational databases with information extracted from
XML. Connect for SQL/XML makes it easy for you to
integrate SQL/XML into your environment. It includes a
graphical Query Builder that allows developers to quickly
create, modify, and test SQL/XML queries without having
to know the details of SQL/XML. In addition, it is
shipped with examples that show how you can use SQL/XML
queries to achieve different results. |
||
SQL/XML, DOM+JDBC, and Proprietary Database Extensions | ||
Now that we have introduced SQL/XML,
let us compare SQL/XML to the other solutions available to
SQL developers today. We use the same simple problem posed
in the first section of this document, show a SQL/XML query
that solves it, and present the code based on several
alternative solutions. Usage Scenario: Customers and
Projects Our scenario includes data
extracted from two different relational tables, a Customers
table and a Projects table, to create an XML document that
lists the projects for each customer: The "Customers" table contains a
customer identifier, customer name, and customer address.
The "Projects" table contains a project identifier,
project name, and customer identifier. Here's the desired XML output for
a single customer: <customer id="4"> <name>Hardware Heaven</name><city>Washington</city> <projects> <project id="2"><name>Pegasus</name></project> <project id="8"><name>Typhoon</name></project> </projects> </customer> The solution to our problem of
generating XML structures from relational data is
straightforward using SQL/XML. In the following solution,
we use the SQL/XML XMLAGG function to build the list of
projects associated with a given customer: SELECT c.CustId, XMLELEMENT(NAME "customer", XMLATTRIBUTES(c.CustId AS "id"), XMLELEMENT(NAME "name",c.Name), XMLELEMENT(NAME "city",c.City), XMLELEMENT(NAME "projects", (SELECT XMLAGG(XMLELEMENT(NAME "project", XMLATTRIBUTES(p.ProjId AS "id"), XMLELEMENT(NAME "name",p.Name))) FROM Projects p WHERE p.CustId=c.CustId))) AS "customer-projects" FROM Customers c The XML values are returned in the columns of a normal SQL result set as shown: Using JDBC and Connect for SQL/XML, we can extract these XML values programmatically from the result set to construct an XML document as shown in the following code: // Create the Connect for SQL/XML JDBC connection connectWithConnectForSQLXML(); // Build SQL/XML query StringBuffer sqlXml = new StringBuffer(); sqlXml.append ( " SELECT "); sqlXml.append ( " c.CustId, "); sqlXml.append ( " XMLELEMENT (NAME \"customer\", "); sqlXml.append ( " XMLATTRIBUTES(c.CustId AS \"id\"), "); sqlXml.append ( " XMLELEMENT(NAME \"name\", c.Name), "); sqlXml.append ( " XMLELEMENT(NAME \"city\", c.City)), "); sqlXml.append ( " XMLELEMENT(NAME \"projects\", " ); sqlXml.append ( " (SELECT XMLAGG(XMLELEMENT(NAME \"project\", "); sqlXml.append ( " XMLATTRIBUTES(p.ProjId AS \"id\"), "); sqlXml.append ( " XMLELEMENT(NAME \"name\",p.Name))) "); sqlXml.append ( " FROM Projects p "); sqlXml.append ( " WHERE p.CustId=c.CustId))) AS \"customer-projects" "); sqlXml.append ( " FROM Customers c "); // Output result header System.out.println( "---------------------------------------" ); System.out.println( "Query result (via getString on XMLType)" ); System.out.println( "---------------------------------------" ); // Execute the SQL/XML query resultSet = stmt.executeQuery(sqlXml.toString()); // Retrieve data from the resultset while ( resultSet.next() ) { XMLType xmlType = (XMLType)resultSet.getObject(1); System.out.println(xmlType.getString()); } resultSet.close();The SQL/XML query that produces the desired result can be easily maintained outside the application within a properties file or database, for example. Because SQL/XML is standards-based, this same query will work across a variety of databases. Although the SQL/XML standard
currently supports queries and not updates, DataDirect
Connect for SQL/XML
provides proprietary extensions to the SQL99 Insert,
Update, and Delete statements that allow you to update
data stored in relational databases with information
extracted from an XML document. You specify XPath
expressions to extract the relevant subset of information
from the XML document. For example, let's assume that a
new project named Gryphon is added for the customer
Hardware Heaven and the resulting XML document looks like
this: <?xml version="1.0" encoding="UTF-8"?> <customers> <customer id="4"> <name>Hardware Heaven</name><city>Washington</city> <projects> <project id="2"><name>Pegasus</name></project> <project id="8"><name>Typhoon</name></project> <project id="11"><name>Gryphon</name></project> </projects> </customer> </customers>To update the Projects database in our example with the new project named Gryphon, we can insert a new row in the Projects table using the proprietary extension for the SQL99 Insert statement provided by Connect for SQL/XML. Our code would look like this: INSERT xml_document('c:/temp/newprojects.xml') into Projects (ProjId, Name, CustId) xml_row_pattern('/customers/customer/projects/project') values(xml_xpath('@id','Integer'), xml_xpath('@name/text()'), xml_xpath('../../@id','Integer') )For more information about XPath, refer to http://www.w3.org/TR/xpath. Custom-coding a solution to solve
our problem is an alternative approach. APIs that can be
used to access the database (for example, JDBC) have been
available for some time. More recently, XML APIs
(primarily, DOM and SAX) have been added to the
developer's arsenal of available tools. Why not
custom-code a solution that directly accesses the
database and passes the information to one of the XML
APIs? Two issues exist with this
approach. The first issue is maintainability. If you
examine the custom-coded example that follows, you can
see that a substantial amount of code is used to
implement a simple conversion. Business requirements tend
to change over time, so it is realistic to assume that
the requirements for the document structure used to
create the XML will probably change. With all this code,
adding a new element from another RDBMS column to the
document structure, for example, can be
time-consuming. The second issue is application
performance. Typically, the queries executed on the
database correspond to the structure of the XML document
being created. The first query selects top-level
elements, and for each nested structure, a new database
query is used. This is not the fastest approach
available, particularly for heavily nested documents
[1]. Here's a code excerpt that uses
JDBC to retrieve the data to be converted from the
database. Code is written to retrieve data from each
relational table, then, additional code is devoted to
joining the data to create a usable XML
document. // Open JDBC Connection String url="jdbc:datadirect:sqlserver://localhost:1433;databaseName=JXTR"; Class.forName("com.ddtek.jdbc.sqlserver.SQLServerDriver"); con=DriverManager.getConnection(url,"demo","secret"); // Create XML document DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance(); DocumentBuilder db=dbf.newDocumentBuilder(); doc=db.newDocument(); // Create the root element Element root=doc.createElement("customers"); doc.appendChild(root); // Create statement and result set for customer information Statement stmt1=con.createStatement(); ResultSet rs1=stmt1.executeQuery( "select c.CustId,c.Name,c.City from Customers c"); // For all selected customers while(rs1.next()) { // Create customer container element Element customer=doc.createElement("customer"); root.appendChild(customer); // "id" attribute and retrieve contents from result set String custId=rs1.getString(1); customer.setAttribute("id",custId); // "name" child element and retrieve contents from result set Element custName=doc.createElement("name"); custName.appendChild(doc.createTextNode(rs1.getString(2))); customer.appendChild(custName); // "city" child element and retrieve contents from result set Element custAddress=doc.createElement("city"); custAddress.appendChild(doc.createTextNode(rs1.getString(3))); customer.appendChild(custAddress); // "projects" child container element Element projects=doc.createElement("projects"); customer.appendChild(projects); // Create statement/result set for project information Statement stmt2=con.createStatement(); ResultSet rs2=stmt2.executeQuery( "select p.ProjId, p.Name from Projects p where p.CustId="+custId); // For all selected projects while(rs2.next()) { // Create project container element Element project=doc.createElement("project"); projects.appendChild(project); // "id" attribute and retrieve contents from result set project.setAttribute("id", rs2.getString(1)); // "name" child element and retrieve contents from result set Element projName=doc.createElement("name"); projName.appendChild(doc.createTextNode(rs2.getString(2))); project.appendChild(projName); } } // 'Print' DOM document (Xerces version) OutputFormat of=new OutputFormat(); of.setIndent(2); Writer ow=(Writer)new OutputStreamWriter(System.out); XMLSerializer xmlS=new XMLSerializer(ow,of); xmlS.serialize(doc); For some time, DB2 has been
shipping an XML integration tool, DB2 XML Extender [2].
With version 8.1, DB2 also supports SQL/XML
[3]. DB2 XML Extender, like all DB2
extenders, works as user-defined data types (UDTs) and
associated user-defined functions (UDFs) that implement
operations on these UDTs. DB2 XML Extender defines three
UDTs: XMLVarchar, XMLCLOB, and XMLFILE. These data types
are used to store XML information in its native format,
and the operations defined on these UDTs manipulate the
XML information. DB2 XML Extender supports two
major modes of operation: XML column mode and XML
collection mode. XML Column
Mode In XML column mode, complete XML
documents are stored in a single database column (using
one of the previously mentioned XML UDTs). Furthermore,
parts of the XML document can be stored in normal RDBMS
(indexed) table columns that are linked to the original
XML document for quick lookup. Although this is certainly
a useful feature, it does not solve the problem of moving
data to and from the relational data model and the XML
data model. XML Collection
Mode XML collection mode supports both
composing and writing XML information from or into DB2
table columns. The XML collection mode has the following
characteristics:
The following contents of a DAD
file implements the mapping for our example. Looking at
the contents of this DAD file, you can see that it
describes the structure of the XML document to create or
consume the XML using element_node and attribute_node
elements and that the mapping between the structure and
the relational information is provided by using the
RDB_node elements. <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE DAD SYSTEM "dad.dtd"> <DAD> <validation>YES</validation> <Xcollection> <prolog>?xml version="1.0"?</prolog> <doctype>!DOCTYPE customers SYSTEM "customers.dtd"</doctype> <root_node> <element_node name="customers"> <element_node name="customer"> <RDB_node> <table name="Customers" key="CustId" /> <table name="Projects" key="ProjId" /> <condition> Customers.CustId=Projects.CustId </condition> </RDB_node> <attribute_node name="id"> <RDB_node> <table name="Customers" /> <column name="CustId" type="integer"/> </RDB_node> <RDB_node> <table name="Projects" /> <column name="CustId" type="integer"/> </RDB_node> </attribute_node> <element_node name="name" > <text_node> <RDB_node> <table name="Customers" /> <column name="Name" type="varchar(50)"/> </RDB_node> </text_node> </element_node> <element_node name="city" > <text_node> <RDB_node> <table name="Customers" /> <column name=“city” type="varchar(50)"/> </RDB_node> </text_node> </element_node> <element_node name="projects"> <element_node name="project"> <attribute_node name="id"> <RDB_node> <table name="Projects" /> <column name="ProjId" type="integer"/> </RDB_node> </attribute_node> <element_node name="name" > <text_node> <RDB_node> <table name="Projects" /> <column name="Name" type="varchar(50)"/> </RDB_node> </text_node> </element_node> </element_node> </element_node> </element_node> </element_node> </root_node> </Xcollection> </DAD>The DAD file can be used to either retrieve the relational data from the database into XML or insert the XML into the database using the stored procedures ddGenXML (to retrieve the relational data and convert it to XML) and dxxShredXML (to insert the XML into the database). Similar to DB2 UDB, Oracle has
been shipping XML integration tools for some time. Prior
to Oracle 9iR2, most of these integration tools were
bundled in a separately downloadable package (Oracle
XDK). With release 9iR2, Oracle positions its database
server also as an XML database server. The Oracle 9iR2
release adds a number of XML-related features, including
SQL/XML support. From the complete set of XML
related modules and features available in Oracle 9iR2,
XML SQL Utility (XSU) [4] and SQL/XML [5] support only
are relevant for the information mapping problem we are
addressing in this document. XML SQL
Utility XSU is packaged as a set of Java
classes. A wrapper PL/SQL package (DBMS_XMLGEN) and a
flexible command-line utility are provided as
well. From Relational to
XML XSU can render the result of any
SQL query into a fixed-format XML structure. The mapping
from query result to XML format takes into account the
features of the Oracle (object) type system and, in
combination with object views defined on top of
non-object typed data, a flexible mapping can be
created. The rules that determine the XML
structure derived from the query result
include:
From XML to
Relational The inverse operation (inserting,
updating, or deleting relational data based on XML
information), is slightly less flexible. For
example:
Using XSU A set of Java classes (and a
PL/SQL package) is provided to execute XSU mappings. A
powerful command-line tool exposes most of the options in
the API. Finally, the XSQL Servlet is provided to support
scalable deployment in Servlet container
engines. XSU Java
Classes The OracleXMLQuery class can be
used to execute a query and retrieve the resulting XML.
Different methods are available to perform the following
tasks:
The OracleXMLSave class can be
used to insert, update, or delete relational information.
The following features are exposed:
XSU Example The following code excerpt shows
the use of the XSU classes. The code extracts the
Customer and Project information from the database, and
creates the XML document shown in our
example. // Open JDBC Connection String url="jdbc:oracle:thin:@localhost:1521:ORA92"; Class.forName("oracle.jdbc.driver.OracleDriver"); con=DriverManager.getConnection(url,"jxtr","jxtr" ); // Query StringBuffer sb=new StringBuffer(); sb.append("SELECT "); sb.append(" c.custid as \"@id\", "); sb.append(" c.name, "); sb.append(" c.City, "); sb.append(" cursor ( "); sb.append(" SELECT "); sb.append(" p.projid as \"@id\", "); sb.append(" p.name "); sb.append(" FROM Projects p "); sb.append(" WHERE p.CustId=c.CustId ) AS projects "); sb.append(" FROM Customers c "); // XSU object OracleXMLQuery q=new OracleXMLQuery(con,sb.toString()); // Result "customization" q.setRowsetTag("customers"); q.setRowTag("customer"); q.useLowerCaseTagNames(); q.setRowIdAttrName(""); // Stylesheet for result "clean-up" q.setXSLT("q.xslt",null); // Generate result document and print Document resDoc=q.getXMLDOM(); XMLDocument oraDoc=(XMLDocument)resDoc; oraDoc.print(System.out);NOTES:
SQL Server 2000, and later,
released SQL/XML and Web Services toolkits that expose a
series of features that allow you to publish relational
data as XML, or populate or update relational information
with data retrieved from an XML document. The following
sections provide an overview of these
features. Transact-SQL Extensions
[6]
The syntax for the FOR XML
extension is: FOR XML [RAW|AUTO|EXPLICIT] [, XMLDATA] [, ELEMENTS] [, BINARY BASE64]
For details about the different
options and parameters, refer to the SQL Server Transact
SQL documentation [6].
sub-trees that become the
individual rows in the rowset. Individual column values
are selected from the XML sub-trees (rows) by specifying
one or more column patterns using XPath. Because the
result of an OPENXML statement is a rowset, its result
can be used as the source for insert, update, or delete
statements. The syntax for the OPENXML
extension is: OPENXML ( idoc int [in], rowpattern nvarchar[in], [flags byte[in]] ) [WITH(SchemaDeclaration|TableName)]NOTE: The idoc parameter contains a handle to a parsed XML document. This handle is created from an XML document by invoking the sp_xml_preparedocument stored procedure. For details about the different
options and parameters, refer to the SQL Server Transact
SQL documentation [6]. Web Services Toolkit
[7]
NOTE: The set of SQL Server
features Microsoft identifies as SQLXML is not based on
the SQL/XML standard. Example The FOR XML extension can be used
to create the XML document from the Customer and Project
table, and OPENXML can be used to insert the information
from the XML document in the database
tables. NOTE: XML views and DiffGram
support similar functionality, but they are not easily
accessible from within a Java program. The following
example is a Java code excerpt that shows how to use the
OPENXML function to update columns in the Customers and
Projects table with information extracted from the
example XML document. ... // Build Transact-SQL statement StringBuffer sb=new StringBuffer(); // Variable declarations sb.append("DECLARE @idoc int\n"); sb.append("DECLARE @doc varchar(3000)\n"); // Define XML document parameter and parse sb.append("SET @doc =?\n"); sb.append("EXEC sp_xml_preparedocument @idoc OUTPUT, @doc\n"); // Update Customers from XML sb.append("update Customers\n"); sb.append(" set Customers.Name=u.Name, Customers.City=u.City\n"); sb.append("FROM OPENXML (@idoc, '/customers/customer',2) \n"); sb.append("WITH (CustId integer '@id', Name varchar(50) 'name/text()',\n"); sb.append(" Address varchar(50) 'address/text()') u\n"); sb.append("where Customers.CustId=u.CustId\n"); // Update Projects from XML sb.append("update Projects\n"); sb.append(" set Projects.Name=u.Name\n"); sb.append("FROM OPENXML (@idoc, '/customers/customer/projects/project',2) \n"); sb.append("WITH (CustId integer '../../@id', ProjId integer '@id',\n "); sb.append(" Name varchar(50) 'name/text()' ) u\n"); sb.append("where Projects.ProjId=u.ProjId\n"); // Release 'parsed' XML document sb.append("EXEC sp_xml_removedocument @idoc\n"); // Create statement and set bind marker value PreparedStatement stmt=con.prepareStatement(sb.toString()); stmt.setString(1,readFile("example.xml")); // Execute stmt.execute(); int rowCount; // Loop through results do { rowCount=stmt.getUpdateCount(); if(rowCount >= 0) { System.out.println("Updated:"+rowCount); stmt.getMoreResults(); } } while( rowCount>=0 ); con.close();The following code excerpt creates a Transact SQL statement that is executed using a PreparedStatement.execute method invocation. The Transact SQL requires only one input parameter, the XML document. The value for this input parameter is provided by invoking PreparedStatement.setString. The Transact SQL statement
contains two OPENXML statements. The first extracts
Customer information from the input XML document and uses
this data to update the Name and Address columns in the
Customers table. The second OPENXML statement extracts
information from the input XML document and uses this
data to update the Name column in the Projects
table. The inverse mapping, creating the
XML document based on the RDBMS table data, can be
achieved with the following Transact SQL FOR XML
statement. SELECT 1 AS Tag, 0 AS Parent, NULL AS [customers!1], NULL AS [jxtr_order_q1!15!!hide], NULL AS [customer!2!id], NULL AS [customer!2!name], NULL AS [projects!3], NULL AS [jxtr_order_q2!16!!hide], NULL AS [project!4!id], NULL AS [project!4!name] UNION ALL SELECT 2,1, NULL ,1,c.CustId,c.Name, NULL , NULL , NULL , NULL from Customers c UNION ALL SELECT 3,2, NULL ,2,c.CustId,c.Name, NULL , NULL , NULL , NULL from Customers c UNION ALL SELECT 4,3, NULL ,3,c.CustId,c.Name, NULL ,1,p.ProjId,p.Name from Customers c , Projects p WHERE ( p.CustId = c.CustId ) ORDER BY 5,6,7,4,9,10,8,Tag FOR XML EXPLICIT |
||
Conclusion | ||
Most database environments use XML,
created from data stored in relational databases, to create
web messages or to display on web sites. In addition,
companies often need to be able to create a variety of XML
documents, containing significantly different structures
and data. To make this easier and as a competitive feature,
almost all relational database vendors have added XML
extensions and XML support. SQL/XML, which is part of SQL 2003,
provides a standard and portable way for developers to
create any XML structure they need by incorporating XML
functions in their SQL queries. For someone who already
knows and uses SQL, SQL/XML is easy to learn and is one of
the simplest approaches to creating XML from relational
data. It is also extremely powerful, allowing the full
power of SQL to be combined with the ability to create any
desired XML structure from query results. Although there
are many other ways to perform the same task, SQL/XML is
simple to use, leverages existing SQL knowledge, and makes
it possible to write portable applications when used with a
JDBC connection. In this document, we compared
SQL/XML to other programming approaches, finding that the
SQL/XML solution requires much less code, is more
efficient, and is easier to write and maintain than
building XML using the DOM and SQL queries. We also found
that solutions using proprietary extensions from the
database vendors are not only non-portable, but are also
harder to learn and are more complex to use than Java
applications that use SQL/XML and a JDBC
connection. DataDirect Technologies provides a cross-platform implementation of SQL/XML that allows JDBC programs to access most major databases including Microsoft SQL Server, DB2, Informix, Oracle, and Sybase. It also provides an implementation of the XML data type, which will not be part of the JDBC standard until at least JDBC 4.0, and support for updates, which will not be part of SQL/XML in SQL 2003, but is expected to be added later. |
||
References | ||
[1] Shanmugasundaram, et. al. (2000)
Efficiently Publishing Relational Data as XML
Documents, Proc. of the 26th International Conference
on Very Large Databases, Cairo, Egypt, 65-76. [2] IBM DB2 Universal Database,
XML Extender Administration and Programming, Version
8 [3] IBM DB2 Universal Database,
SQL Reference Volume 1, Version 8 [4] Oracle 9i, XML
Developer’s Kit Guide – XDK, Release 2
(9.2) [5] Oracle 9i, XML Database
Developer’s Guide – Oracle XML DB,
Release 2 (9.2) [6] Microsoft SQL Server 2000
Documentation [7] Microsoft SQL/XML 3.0
Documentation [8] “XML-Related specs
(SQL/XML)”. ISO/IEC JTC 1/SC 23
N00575, WG3:HEL-026R2,H2-2000-331R2, Jim
Melton, October 10, 2000 [9] Database Languages – SQL
- Part 14: XML Related Specifications (SQL/XML),
H2-2002-574, WG3:ZSH-020, Jim Melton (Editor), December
2002 |
ODBC driver | JDBC driver | ADO.NET provider | SQL/XML
XQuery | XML Editor | Legal | Privacy | Trademarks
Copyright © 1993-2004 DataDirect Technologies. All Rights Reserved.