Les utilitaires "XML-SQL" d'Oracle correspondent à
des classes Java offrant deux principales fonctionnalités
:
- Extraire des données d'une base au format XML.
- Insérer des données au format XML dans une base.
Cet outil est fourni en standard à partir d'Oracle
8i (version 8.1.7 et plus) ainsi que sous Oracle 9i.
Pour se connecter aux données, "XML-SQL" utilise
des connexions JDBC.
Bien que cet utilitaire puisse fonctionner avec n'importe quel driver
JDBC, ceux fournis par Oracle sont optimisés.
De la base vers le schéma XML
La classe "OracleXMLQuery" permet de construire un document
XML à partir d'une requête SQL. Voici un exemple basique
de son utilisation : (source Oracle)
import java.sql.*;
import oracle.xml.sql.query.*;
import oracle.jdbc.driver.*;
public class sample
{
public static void main(String args[])
throws Exception
{
DriverManager.registerDriver(new
oracle.jdbc.driver.OracleDriver());
Connection
conn =
DriverManager.getConnection("jdbc:oracle:oci8:scott/tiger@");
OracleXMLQuery
qry = new OracleXMLQuery(conn, "select * from employes");
System.out.println(qry.getXMLString());
conn.close();
}
}
Si nous considérons que la table "employes" a
été créee par le script suivant :
CREATE TABLE employes (
EMPNO NUMBER,
ENAME VARCHAR2(20),
JOB VARCHAR2(20),
MGR NUMBER,
HIREDATE DATE,
SAL NUMBER,
DEPTNO NUMBER
);
... alors, suite à la requête "select
* from employes", notre fichier XML ressemblera à
ceci :
<?xml version='1.0'?>
<ROWSET>
<ROW num="1">
<EMPNO>7369</EMPNO>
<ENAME>Smith</ENAME>
<JOB>CLERK</JOB>
<MGR>7902</MGR>
<HIREDATE>12/17/1980
0:0:0</HIREDATE>
<SAL>800</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<!-- rangées supplémentaires...
-->
</ROWSET>
(Afin de rendre ce code encore plus clair, vous pouvez le
copier/coller dans un fichier.xml et l'ouvrir sous IE5 par exemple).
Notre document XML a donc été conçu grâce
à l'exploitation d'un resultset JDBC par la classe
"OracleXMLQuery". On note que les noms des balises XML
sont issus des noms de colonnes de la requête SQL (des alias
peuvent aussi être utilisés). <ROWSET>"
constitue le tag "racine" du document XML, il entoure
chacun des tags "<ROW...> (comportant un numéro),
qui eux-mêmes délimitent chacun des tuples ramenés
par la requête.
Si ce cas "d'école" a le mérite d'être
simple, il ne correspond pas forcément aux structures de
données d'une "vraie" base. Que faire par exemple
face à une table construite autour de type définis
par l'utilisateur ? Exemple : (source Oracle)
(Une adresse est d'abord créée sous forme d'un objet)
CREATE TYPE AddressType AS OBJECT (
STREET VARCHAR2(20),
CITY VARCHAR2(20),
STATE CHAR(2),
ZIP VARCHAR2(10)
);
Cet objet "AdressType" est ensuite utilisé en
tant qu'attribut au sein d'un autre objet "EmployesType"
:
CREATE TYPE EmployesType AS OBJECT
(
EMPNO NUMBER,
ENAME VARCHAR2(20),
SALARY NUMBER,
EMPADDR AddressType
);
Pour corser le tout, on retrouve "EmployesType" dans
une collection de type :
CREATE TYPE EmployeeListType AS TABLE OF EmployeeType;
Enfin, la table "dept" est créee, elle compte
parmi ses attributs un objet et une collection d'objets :
CREATE TABLE dept (
DEPTNO NUMBER,
DEPTNAME VARCHAR2(20),
DEPTADDR AddressType,
EMPLIST EmployeeListType
);
Afin de ne pas surcharger cet article, la version xml obtenue se
trouve dans ce document.
Lorsqu'un attribut de type objet (comme "AddressType")
existe dans une table, il est "remplacé" lors de
la création du document XML par les noms des colonnes utilisés
lors de sa création. Ainsi les "sous-éléments"
du tag "<DEPTADDR>" vont être "<STREET>",
"<CITY>", "<STATE>", et "<ZIP>".
De la même manière, mais avec des niveaux d'imbrication
supplémentaires, "EMPLIST", collection d'objets,
se transforme en une hiérarchie de tags imbriqués
selon la façon dont ils ont été définis.
Du schéma XML vers la base
La classe Oracle prévue à cet effet se nomme "OracleXMLSave".
Elle est capable d'insérer, de mettre à jour et de
supprimer des données XML. Toutefois, sa seule utilisation
ne permet pas de pouvoir insérer dans la base de données
des documents XML, parfois complexes. Il faut en effet créer
une structure Oracle (objet, vue) correspondant à l'architecture
de ces documents.
En fait, si le chemin à parcourir pour aller des données
XML vers la base n'est que "l'inverse" de celui qu'on
emprunte pour engendrer du XML à partir de la base, il existe
tout de même une différence de taille entre les deux
: Il n'existe pas de "mapping" entre les
attributs XML (les tags) et les champs de la base de données.
D'où la necessité de créer une "structure
d'accueil" sur mesure pour les documents XML.
Prenons les tags XML suivants :
<DEPT>
<DEPTNO>100</DEPTNO>
<DEPTNAME>Sports</DEPTNAME>
<DEPTADDR>Paris</DEPTADDR>
<EMPLIST>
<EMPLIST_ITEM>
<EMPNO>7369</EMPNO>
<ENAME>Sebastien</ENAME>
<SALARY>10000</SALARY>
</EMPLIST_ITEM>
<!--
employes supplementaires... -->
</EMPLIST>
</DEPT>
Il va maintenant s'agir de créer les tables Oracle adaptées
pour les "réceptionner". Nous devons également
faire correspondre certaines parties de la structure XML à
des types que nous allons définir :
- "emp_type" : Les informations liées à
l'employé (identifiant, nom, salaire), correspond à
<EMPLIST_ITEM>.
- "empc_type" : Décrira une "collection"
d'employés, correspond à <EMPLIST>.
- "dept_type" : Définit un département,
correspond à <DEPT>.
Au final, des liaisons existent entre chacun de ces types, ils
s'imbriquent ici de la manière suivante :
CREATE OR REPLACE TYPE emp_type AS OBJECT
(
empno NUMBER(4),
ename VARCHAR2(50),
salary NUMBER(6,2)
);
CREATE TYPE empc_type AS TABLE OF emp_type;
CREATE TYPE dept_type AS OBJECT (
deptno NUMBER(3),
deptname VARCHAR2(50),
deptaddr VARCHAR2(50),
employes EMPC_TYPE
);
Les types étant définis, les données XML peuvent
être importées et la table (objet) Oracle peut être
créee :
CREATE TABLE obj_dept OF dept_type
NESTED TABLE employes STORE as nested_emp_table;
Si l'on souhaite conserver une structure de tables relationnelles
il faut alors passer par une vue :
CREATE VIEW v_dept OF dept_type WITH OBJECT
OID(deptno) AS
SELECT d.deptno, d.deptname, d.deptaddr,
CAST ( MULTISET ( SELECT e.empno,
e.ename, e.salary
FROM
emp e WHERE e.deptno = d.deptno)
AS empc_type)
FROM dept d;
Il existe d'autres moyens d'interfacer XML et une base de données.
Cela dépend du SGBD utilisé ainsi que de la technologie
que l'on souhaite employer. Du Perl en passant par le Java, les
bases de données relationnelles multiplient leurs interactions
avec XML, de quoi freiner un peu plus la progression des bases natives
XML ?
|