With the release of IBM's DB2 9, formerly known as Viper and currently in Release Candidate, IBM also plans to unveil the new DB2 9 Developer Workbench. Existing DB2 users will recognize the functionality as the current DB2 Development Center. But the new version, available as a free download, has been decoupled from the Viper administrative tools and re-visioned on an Eclipse platform.
The Workbench can be downloaded from the DB2 Download Center. If you're not quite ready or don't have the bandwidth for it, then use this walkthrough as your introduction to the new UI and key features, particularly the XQuery Visual Builder.
| For developers who have come to know and love the free version of DB2, known as DB2 Express-C, good news! DB2 Express-C 9, which will be released with the fee-based versions, also includes pureXML capabilities. |
XQuery Visual Builder
While the native XML capabilities of DB2 9 have been getting a lot of digital ink lately (IBM's marketing gurus have recently dubbed it "pureXML"), less attention has been paid to what the Workbench does with that XML. Since XML is stored in DB2 tables as neither a CLOB nor parsed relational fields, developers need something other than SQL to query it.
XQuery, or XML Query Language, has long been in development and is currently in Candidate Recommendation with the W3C. For more information than you will probably ever need, you can read the W3C Documentation, XQuery 1.0: An XML Query Language.
While supposedly it's syntactically similar to SQL, its differences number more than enough to warrant separate and prolonged study. Fortunately for those of us new to XQuery, the Workbench provides a visual designer, which, in the proper hands, can make short work of even complex queries.
That said, the visual designer itself is not without its quirks, as you'll see. If you're planning to use XQuery but are just beginning to learn the basics, this walkthrough will help familiarize you with key concepts. Use the Visual Builder to piece together your queries, then study the auto-generated syntax created by the Workbench. (Remember the days of using a visual designer to learn SQL? Same thing. Except that working with nested XML nodes is unlike any SQL diagram you've ever drawn.)
But once you've learned the basics, you'll want to take it further. Learn XQuery syntax. Play with it in the Command Editor. Mix it up with SQL, which I'll touch on after the walkthroughs. In short, this is just an intro. The Workbench tools can be tricky to grasp at first, but once you do, you'll wonder how you ever got work done without them. But to truly prepare for the next stage of XML storage represented by DB2 9, use the Workbench as not just a tool in and of itself, but as an aide to learning.
Back to Shakespeare: A New Workbench Project
If you read "XML and Beyond," then you're somewhat familiar with the XML storage capabilities of DB2 9. In fact, if you completed then walkthrough, then you should have a working copy of a sample table filled with some heavy XML documents consisting of a few of Willie Shakespeare's finest works. The following walkthrough builds on that example by introducing the XQuery Visual Builder and pulling data from those plays.
If you want to experiment with the Shakespeare database, then download DB2 9 and complete the walkthrough. Otherwise, you can follow along with similar queries against the SAMPLE database that comes with DB2. If nothing else, the walkthrough should at least give you some notion of what to expect in the DB2 9 Workbench.
This walkthrough assumes you have DB2 9 installed and have created a SHAKES database, with a PLAYS table that includes the following columns and contains at least three rows, each with an XML document containing the full text of a play in the PLAYTEXT column:
"PLAYID" INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY
"PLAYNAME" VARCHAR(50) NOT NULL
"PLAYTEXT" XML NOT NULL
![]() Figure 1. New Connection to SHAKES |
![]() Figure 2. New Data Project and Connection |
When you click "Finish", the wizard will create a new project for you under the Data Project Explorer. If you selected to create a new connection, it will also create that connection and enable it. You can explore the connection in the Database Explorer, drilling down all the way to the column if you want (see Figure 2).
![]() Figure 3. Entire Workspace |
Look at Figure 3 for a larger view of the entire workspace. This is the "Data" perspective. Note the default arrangement of the various Views. The Eclipse framework gives you almost complete freedom of choice when it comes to UI layout. You can dock, tab, or float to your heart's content with any number of Views included in the Workbench.
The Play's the Thing: XQuerying XML Nodes
XML Queries require a representative schema to populate the Visual Builder. You can add XSDs to the "XML Schema Documents" folder to facilitate the process of associating them with the XML columns you want to query. You can also add a Document Type Definition (DTD) or schema to the workspace.
But just to show off, you're going to let the Workbench discover and generate the XML schema on its own.
![]() Figure 4. Sample Column Document |
![]() Figure 5. Associate Document with XML Column |
![]() Figure 6. New PersonaQuery ![]() Figure 7. New Persona Node |
The tricky thing about using such a complex example as a Shakespearean play is that you have a ton of nodes to work with. Though fairly visual and certainly helpful in crafting XQuery syntax, the visual designer is not especially intuitive. You'll find it quite easy to pull in the wrong node or put the right node in the wrong place or perform a mismatched operation. The visual designer is friendly enough to let you make all the mistakes you want. When you try to run them, you'll just get an error (and not a very helpful one, at that, in all likelihood).
Of course, the best way to learn is to bang your head against the wall a few times until you break through. But to save you some headache and keep this example fairly straightforward, I'll step you through a sample query.
![]() Figure 8. Step Into |
![]() Figure 9. For, Let, Where, Order By, Return ![]() Figure 10. Expanded Function List ![]() Figure 11. matches() function ![]() Figure 12. matches() function Completed ![]() Figure 13. Completed FLWOR |
The FLWOR, which stands for FOR, LET, WHERE, ORDER BY, RETURN, is XQuery's most basic syntax, the rough equivalent to SQL's SELECT-FROM-WHERE. This is where you define the node that will be iterated through in performing the query, a binding variable to serve as a sort of anchor for the query, your conditions, and the nodes to be returned. You can specify the variable name or accept the default, in this case "PERSONA0" (see Figure 9).
The magic for this query happens in the Where clause. The goal: find every play in which one of the characters is a King or somehow related to a King. Here, you have a couple of options. Though XQuery doesn't use the keyword LIKE, it does provide a ton of functions, including contains() and matches(). In this case, contains() won't quite work because of case sensitivity. But matches() gives you highly flexible pattern-matching, including an "ignore case" switch. To use it, expand the Functions category on the left and, if not already selected, pick String Functions from the dropdown (see Figure 10).
At this point your XQuery is complete. From the Step Into dropdown, choose "Run..." You'll see a new request for document association, but since you've already done that you can accept the default and choose Finish.
If all goes well, in your Data Output view (see Figure 14), you'll see a Success status on the left and a parent node and ellipsis on the right with your results. Click the ellipsis.
The plays used in this example feature the following Kings and their relations. In fact, the match worked so well that the results also include one "DUKE of BUCKINGHAM".
<PERSONA>KING OF FRANCE</PERSONA>
<TITLE>All's Well That Ends Well</TITLE>
<PERSONA>FERDINAND, king of Navarre.</PERSONA>
<TITLE>Love's Labor's Lost</TITLE>
<PERSONA>KING EDWARD The Fourth</PERSONA>
<TITLE>The Tragedy of Richard the Third</TITLE>
<PERSONA>HENRY, Earl of Richmond, afterwards King Henry VII.</PERSONA>
<TITLE>The Tragedy of Richard the Third</TITLE>
<PERSONA>DUKE of BUCKINGHAM</PERSONA>
<TITLE>The Tragedy of Richard the Third</TITLE>
<PERSONA>ELIZABETH, Queen to King Edward IV. </PERSONA>
<TITLE>The Tragedy of Richard the Third</TITLE>
<PERSONA>MARGARET, Widow of King Henry VI. </PERSONA>
<TITLE>The Tragedy of Richard the Third</TITLE>
<PERSONA>DUCHESS of YORK, Mother to King Edward IV.</PERSONA>
<TITLE>The Tragedy of Richard the Third</TITLE>
<PERSONA>LADY ANNE, Widow of Edward Prince of Wales, son to King Henry VI;
afterwards married to Richard.</PERSONA>
<TITLE>The Tragedy of Richard the Third</TITLE>
![]() Figure 14. Data Output View |
Now here's the best part: at the bottom of your XQM frame, you should see two tabsDesign and Source. Look at the source code that the designer generated for you. You should see something like:
values(XMLQUERY('
declare boundary-space strip;
for $PERSONA0 in
db2-fn:xmlcolumn("PLAYS.PLAYTEXT")/PLAY/PERSONAE/PERSONA
where matches ( $PERSONA0,"king","i" )
return
(
$PERSONA0,
$PERSONA0/../../TITLE
)
' RETURNING SEQUENCE))
Use this to learn from, or to generate XQuery code to be incorporated elsewhere. In fact, you can take it directly to the Command Editor and generate the same results with some minor modifications:
xquery
for $PERSONA0 in
db2-fn:xmlcolumn("PLAYS.PLAYTEXT")/PLAY/PERSONAE/PERSONA
where matches ( $PERSONA0,"king","i" )
return
(
$PERSONA0,
$PERSONA0/../../TITLE
)
For Extra CreditTip #1: since you created an XML Schema in the last example, you can use that same file as the representative example here (look under Local Workspace). Only this time, you'll need to manually associate it with your data.
Tip #2: the node you want is LINE, which can be found under PLAY/ACT/SCENE/SPEECH. You'll see a sister node SPEAKER and can grab TITLE from the same place as the previous example.
![]() Figure 15. SAMPLE.CUSTOMER Table |
Mixing XQuery and SQL
In addition to adding the Powers of XQuery to your collection of mutant abilities, you'll still have many reasons to call upon your SQL skills. For that reason, it'll be handy to mix the two, which DB2 9 does ably and elegantly.
For a quick demo, open up your Control Center and connect to the SAMPLE database. If you need to create this database, run the db2sampl utility. Several of the tables in the DB2 9 version of SAMPLE include XML fields. Look at the CUSTOMER table (Figure 15)it has two XML fields, INFO and HISTORY.
To view the XML data, double-click the table to open it. INFO and HISTORY will both appear to be blank. Click "Fetch XML" to populate them, then click on one of the INFO cells. An ellipsis will appear that takes you to an XML Document Viewer. HISTORY contains no information in the default SAMPLE database. Open the Command Editor and run the following commands:
![]() Figure 16. Results of SELECT Query |
connect to SAMPLE;
select * from customer;
You should see the results in Figure 16a list of rows, with some XML.
Now run just the select statement. The results will instead appear in the Query Results tab of the Command Editor. But here's a slight gotcha: though you can click "Fetch XML" to populate the XML fields, you can't currently click the ellipses to view the XML data, as you could when you opened the table directly. Whether it's a bug or a "feature", it's not going to get in your way here, but is something you should know about.
Suppose you want to select your rows based on the city of the customer, such as all customers in Toronto. You can enter the following XQuery statement directly:
xquery
for $c in db2-fn:xmlcolumn('CUSTOMER.INFO')
/customerinfo/addr/city
return $c
Notice a few things:
![]() Figure 17. XQuery Results ![]() Figure 18. Results of XQuery Statement |
You can also shorten this statement to:
xquery
db2-fn:xmlcolumn('CUSTOMER.INFO')/customerinfo/addr/city
This produces the results in Figure 17.
To pull the customers who live in Toronto, use something like:
xquery
db2-fn:xmlcolumn("CUSTOMER.INFO")/customerinfo/name
[./../addr/city = "Toronto"]
You should get the results you see in Figure 18.
So far, all of this can be done quicker and easier in the XQuery Visual Builder (in fact, I had to use it to build that last statement). But suppose you needed to mix up some SQL code with all of this, perhaps for a SQL stored procedure. The following statement returns the CID using the same conditional, but in the context of SQL:
select CID from CUSTOMER
where xmlexists('$c/customerinfo/addr[city="Toronto"]'
passing CUSTOMER.INFO as "c")
Note:
One more example. This one's a bit more complicated: it pulls a list of employees whose last names match the name of a customer. It's completely irrelevant but shows how to link the relational fields of one table with XML nodes of another.
select CUSTOMER.CID,
EMPLOYEE.EMPNO,
EMPLOYEE.FIRSTNME,
EMPLOYEE.LASTNAME
from CUSTOMER, EMPLOYEE
where xmlexists('$c/customerinfo/name[matches(.,$l,"i")]'
passing INFO as "c", EMPLOYEE.LASTNAME as "l")
What to notice here:
![]() Figure 19. Results of SQL and XQuery Combination |
See Figure 19 for the results of this query, which is returned in table format.
For Extra Credit
Right now, this query doesn't return any XML data. For comparison, pull the CUSTOMER name that's being matched. Use the /customerinfo/name node. Also, try experimenting with the xmltable() function to return XML results in tabular format.
Where to Go from Here
This walkthrough covers a lot of ground. But even so, it barely scratches the surface of what the DB2 9 Workbench is capable of, even just in the area of XQueries. For more information on the Workbench, the Help files included with your install actually contain quite a bit of good information, unlike the Help files of other IDEs we know and love. You'll find abundant information about XQuery syntax and even some tutorials to help get you started on various Workbench features.
Also be sure to check out the following resources:
On the subject of combining XQuery with SQL, you have a couple of excellent resources: