L'avenir de SQL : SQL 3, XML, XQL

SQLPro

L'avenir de SQL passe par différentes phases. Tout d'abord en 1999, une nouvelle version de SQL a été normalisée. C'est SQL 3. Elle apporte une grande avancée dans le domaine du relationnel objet. Ensuite, c'est vers les standards du Web qu'il faut se tourner pour comprendre les révolutions qui vont atteindre les SGBDR. Ces révolutions s'appellent XML et XQL...

- Titre : L'avenir de SQL : SQL 3, XML, XQL

- Auteur : SQLPro

- Parution : 26 août 2003

- Mise à jour : 10 mars 2009

- Licence : Copyright ® 2003 Frédéric Brouard. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- 1. Une brève présentation de SQL 3

- 1-1. Déclencheurs (Triggers)

- 1-2. Extension du langage

- 1-3. Bibliothèque de code (PSM - Persistent Stored Module)

- 1-4. Types abstraits

- 1-5. et encore...

- 2. XML, XQL et les bases de données

- 2-1. eXtended Markup Language (XML)

- 2-2. eXtended Query Language (XQL)

1 - Une brève présentation de SQL 3

Le dépôt de la norme de la nouvelle version de SQL, intitulée SQL 3 (1999) s'est effectué peu avant l'arrivée de l'an 2000. D'ici a ce que ses éléments essentiels soient implantés au sein des principaux SGBDR il devrait s'écouler plusieurs années. Nous sommes en 2001 et seuls les éditeurs Oracle, IBM et Informix ont commencés à communiquer sur le sujet.

Nous allons voir que SQL 3 présente de notables avancées, notamment en matière de types de données, dans la programmation des SGBDR et dans le concept du relationnel objet.

1-1 - Déclencheurs (Triggers)

Inexistant dans la norme SQL 2, mais la plupart du temps implanté par les constructeurs de SGBDR, les triggers deviennent avec SQL 3 une réalité incontournable. Rappelons brièvement ce qu'est un trigger : un trigger n'est qu'un simple intercepteur d'événement spécifique aux bases de données. Sa granularité est définie au niveau de la table.

La syntaxe d'un trigger SQL 3 est la suivante :

CREATE TRIGGER nom_trigger
BEFORE | AFTER
INSERT | DELETE | UPDATE [ OF liste_colonne ]
ON nom_table
[REFERENCING   OLD [ROW] [AS] nom_anciennes_valeurs_ligne
| NEW [ROW] [AS] nom_nouvelles_valeurs_ligne
| OLD TABLE [AS] nom_anciennes_valeurs_table
| NEW TABLE [AS] nom_nouvelles_valeurs_table]
FOR EACH STATEMENT | ROW
[WHEN condition]
BEGIN [ATOMIC]
code_trigger
END

On peut remarquer que les triggers de SQL 3 ont une granularité assez fine puisqu'ils permettent de poser du code exécutable avant ou après les événements d'insertion, de suppression ou de modification, et dans ce derniers cas, avec un filtre d'exécution sur les colonnes modifiées.

Exemple :

CREATE TRIGGER verif_prix_remisee
BEFORE UPDATE (prix_uht, quantite, remise)
ON commande
REFERENCING OLD ROW AS old_row_values
NEW ROW AS new_row_values
FOR EACH ROW
WHEN new_row_values.remise > old_row_values.prix_uht * new_row_values.quantite
BEGIN ATOMIC
DECLARE message VARCHAR(255)
new_row_values.remise = old_row_values.remise
SET message = 'Table COMMANDE, client ' ||
cast(new_row_values.cli_id as CHAR(32))
INSERT INTO ALERTE (USER, TROUBLE, DATE_HEURE, LOCALISATION)
VALUES (CURRENT_USER, 'Dépassement de remise acceptable',
CURRENT_TIMESTAMP, Message)
END

Ce trigger est déclenché si une mise à jour intervient sur la table COMMANDE et uniquement si l'une au moins des colonnes PRIX_UHT, QUANTITE ou REMISE est modifiée. Il réaffecte la nouvelle valeur de la remise si celle ci dépasse l'ancien prix multiplié par la quantité actuelle. En outre il insère un enregistrement dans la table ALERTE.

Le mot clef ATOMIC, précise que le corps du trigger doit être exécuté comme un transaction, c'est à dire d'un seul coup sans concurrence (exécution atomique).

On pourra remarquer que ce type de trigger est beaucoup plus proche de ceux d'Oracle que de ceux de SQL Server.

1-2 - Extension du langage

Du fait de l'introduction des triggers et de nombreuses autres extensions, le langage SQL 3 se dote d'une syntaxe plus fournie. Il devient un véritable langage procédural et se trouve proche des syntaxes d'Ada ou de Pascal.

C'est ainsi que l'on y trouve la notion de bloc, définie par les mots clefs BEGIN et END. La déclaration de variable s'effectue à l'aide du mot clef DECLARE et l'assignation à l'aide du mot clef SET. Des structures conditionnelles nouvelles voient le jour : IF, FOR, LOOP, REPEAT, DO WHILE, DO UNTIL, WHILE, LEAVE. La gestion des exceptions est maintenant une réalité, d'autant que les codes de retour d'anomalies ont été étoffés, et qu'il est possible de propager les erreurs vers les conteneurs à l'aide des mots clef SIGNAL et RESIGNAL, un peu à la manière des RAISE ERROR du langage Ada.

Enfin la visibilité externe, comme l'encapsulation dans les langages hôtes sont renforcés grâce à SQL/CLI (Call-Level Interface, déjà présent dans la version 2 de SQL), véritable interface entre les applications et le SQL dynamique.

Pour terminer, disons que les éléments les plus audacieux dans le domaine du relationnel objet sont, les Persistent Stored Module (PSM), véritables bibliothèques de procédures et les routines qui permettent de réaliser des fonctions utilisable a différents niveaux.

1-3 - Bibliothèque de code (PSM - Persistent Stored Module)

Depuis SQL 2 existait la notion de "module" permettant de lancer du SQL dit "dynamique". Cette notion devient plus importante du fait de la percée du relationnel objet et SQL 3 y répond à l'aide des PSM (Persistent Stored Module) englobant fonctions et procédures. Dans les deux cas, on est proche des UDF ou User Define Function, introduite notamment par InterBase de Borland.

Un PSM que nous appellerons bibliothèque, se construit par exemple de la manière suivante :

MODULE gestion_compte LANGUAGE SQL;
DECLARE total DECIMAL(16,2);
FUNCTION solde (SQLCODE, client_id) RETURNS FLOAT;
SELECT SUM(CPT_CREDIT) - SUM(CPT_DEBIT) INTO total
FROM COMPTE_BANCAIRE
WHERE CLI_ID = client_id;
RETURN total;
PROCEDURE credite (SQLCODE, client_id, montant DECIMAL(16,2));
INSERT INTO COMPTE BANCAIRE (CLI_ID, CPT_CREDIT, DATE_HEURE_TRANSACTION)
VALUES (client_id, montant, CURRENT_TIMESTAMP);
PROCEDURE debite (SQLCODE, client_id, montant DECIMAL(16,2))
INSERT INTO COMPTE BANCAIRE (CLI_ID, CPT_DEBIT, DATE_HEURE_TRANSACTION)
VALUES (client_id, montant, CURRENT_TIMESTAMP);
END MODULE;

Ce petit module rassemble les fonctions permettant de calculer le solde, de créditer ou de débiter le compte d'un client. Il peut être réalisé dans un autre langage que SQL, parmi ceux prévus par la norme : Ada, C, COBOL, FORTRAN, NUMPS, PASCAL et PL1. Le module est impérativement attaché, soit à un client (donc en dehors d'une base de données spécifique) ou bien au schéma d'une base de données (module serveur).
C'est dans un PSM client que l'on définira les procédures communes à toutes les bases comme le test permettant de savoir si un nombre entier est premier.

1-4 - Types abstraits

SQL 3 introduit quelques nouveaux types de base, comme le BOOLEAN (booléen), BINARY LARGE OBJECT (grand objet binaire), CHARACTER LARGE OBJECT (BLOB de type chaîne de caractères), ROW (colonne - comme une colonne de table), SET (ensemble de valeurs ), MULTISET (combinaisons de SET) et LIST (liste).

Dans SQL 3 le typage des données peut devenir fort à l'aide du mot clef DISTINCT.

Exemple :

CREATE DISTINCT TYPE DT_TEMPERATURE AS FLOAT
CREATE DISTINCT TYPE DT_VOLTAGE     AS FLOAT

Dès lors une colonne créée avec le type DT_TEMPERATURE ne pourra plus être comparée à une colonne créée avec le type DT_VOLTAGE ce qui empêche le mélange des torchons et des serviettes. En outre, et pour renforcer un tel typage il est possible de redéfinir ce que les opérateurs (+ - * /) et la comparaison (= et <) peuvent faire sur cette définition de type.

Mais c'est avec les Abstract Data Type (ADT) que SQL 3 introduit une véritable révolution... Un type abstrait peut encapsuler n'importe quel type de base et peut être constitué de plusieurs attributs pouvant même être virtuels (méthodes). Bien entendu, et la visibilité de ces attributs répond aux principes objets à l'aide des mots clefs PUBLIC (visibilité externe), PRIVATE (visibilité interne) et PROTECTED (visibilité limitée aux descendants).

Exemple :

CREATE TYPE ADT_ADRESSE
(ADR_LIGNE1    VARCHAR(32),
ADR_LIGNE2    VARCHAR(32),
ADR_LIGNE3    VARCHAR(32),
ADR_CODE_POST CHAR(5),
ADR_VILLE     VARCHAR(32))

CREATE TYPE ADT_PERSONNE
(PRS_NOM            CHAR(64),
PRS_PRENOM         CHAR(32),
PRS_DATE_NAISSANCE DATE,
PRS_DOMICILE       ADT_ADRESSE,
PRS_TITRE          CHAR(6),
PRIVATE PRS_SEXE   BOOLEAN DEFAULT 0)

PUBLIC FONCTION AGE (une_personne ADT_PERSONNE) RETURN FLOAT
BEGIN
DECLARE : une_personne ADT_PERSONNE;
DECLARE : retval FLOAT;
CASE PRS_DATE_NAISSANCE(une_personne);
WHEN IS NULL THEN SET retval = -1;
OTHERWISE SET retval = CURRENT_DATE - PRS_DATE_NAISSANCE(une_personne);
RETURN retval;
END;

Cet exemple définit les types abstraits ADT_ADRESSE (adresse) et ADT_PERSONNE (personne). ADT_PERSONNE contient un attributs privé qui peut par exemple être mis à jour en fonction des insert et des update en correspondance avec le choix du titre saisi ('M.' => Masculin donc 0, 'Mme.' et 'Melle.' => Féminin donc 1). De plus une méthode de calcul d'âge, de portée publique, a été encapsulée dans le type personne et retournera l'âge de la personne à la date du jour en fonction des données rentrées dans l'attribut PRS_DATE_NAISSANCE.

Bien entendu les types abstraits possèdent un constructeur et un destructeur. Le constructeur peut pré-initialiser certains attributs et le destructeur peut exécuter des routines de nettoyage avant de finaliser la destruction.

L'accès aux données d'un objet de la base élaboré à partir d'un type abstrait se fait soit à l'aide d'imbrication de parenthèse, soit à l'aide d'une notation doublement pointée.

Exemple :

CREATE TABLE T_CLIENT
(CLI_ID INTEGER,
CLI_PERS ADT_PERSONNE)

INSERT INTO T_CLIENT
VALUES (1,
CLI_PERS('DUPONT', 'Franck', '1960-11-18',
PRS_DOMICILE('124 rue d''alésia', '','', '75014', 'PARIS')),
'M.')

SELECT CLI_ID, CLI_PERS..PRS_NOM
FROM   T_CLIENT
WHERE  CLI_PERS..PRS_DOMICILE..ADR_VILLE LIKE 'paris%'

CLI_ID     CLI_PERS..PRS_NOM
---------- -----------------------
1          DUPONT

La notation doublement pointée s'explique par le fait que la notation en pointage simple est déjà utilisée pour les surnoms donnés aux tables notamment dans les jointures et les sous requêtes corrélées.

Comme une table peut désormais posséder des sous tables avec SQL 3, il est possible d'activer l'héritage dans un ordre de création :

CREATE TABLE CLIENT UNDER PERSONNE WITH (ENSEIGNE VARCHAR(255))

On pourrait encore dire bien des choses sur les types abstraits de la norme SQL 3, mais je laisse aux spécialistes et aux théoriciens la parole en ce domaine et on trouvera sur le web et dans les actuelles publication de nombreux éléments pour poursuivre sa lecture.

1-5 - et encore...

Un élément gênant dans les précédentes normes était l'impossibilité d'effectuer des requêtes récursives. C'est chose révolue maintenant avec SQL 3 qui permet la récursivité à l'aide de la notion d'"expression de table", définie par la clause WITH. Dès lors il est possible de demander une exécution récursive de la requête (mot clef RECURSIVE) et de préciser la condition d'arrêt dans une clause CYCLE.
Un tel mécanisme permet de modéliser plus facilement les graphes et les arbres et de travailler plus facilement dans les données les représentants.

Les schémas d'ordonnancement sont aussi des nouveautés de SQL 3 et permettent de définir comme objet spécifique à une base de données un ordre de tri indépendant des jeux de caractères.

L'introduction du type booléen nécessite l'existence d'un prédicat "booléen". Le voici donc :

condition IS [NOT] FALSE | TRUE | UNKNOWN

Et nous retrouvons bien là une logique à trois états.

En matière de gestion des transactions, la norme SQL 3 permet de définir de début d'une transaction (START TRANSACTION) mais aussi des points intermédiaires (SAVE POINT) et tout ceci de manière nominative.

En matière de droits d'accès, SQL 3 introduit la notion de rôle qui sont une collections de privilèges ou de droits qu'un utilisateur peut se voir confié.

Enfin trois extensions importantes à SQL 3 sont d'ores et déjà prévues. Elle seront clairement définies dans la future norme SQL 4. Il s'agit de SQL Object, de la gestion du multimédia, et de SQL/TR pour les applications de type temps réel.

2 - XML, XQL et les bases de données

La montée d'Internet a produit différents standards induits par l'obligation de faire coopérer des systèmes d'exploitation et des interfaces graphiques venant de différents horizons. Parmi ces standard, le langage XML déjà très présent et le langage XQL encore peu répandu, vont tout deux venir bouleverser le monde des bases de données.

2-1 - eXtended Markup Language (XML)

XML (eXtended Markup Language) est un langage de description de données qui présente une avancée majeure par rapport au HTML (Hyper Text Markup Language).
Les langages HTML et XML sont des langages descriptifs utilisant des balises qui sont interprétées en général à la volée pour mettre en forme les données, soit sur le plan graphique (HTML) soit sur le plan relationnel ou structurel (XML).

Autant le langage HTML actuellement très utilisé pour une grande majorité de site web fut un des moteurs de la montée en puissance du web, autant on s'est aperçut qu'il devenait un frein pour la dynamisation des sites web simplement par le fait que HTML mélange données et présentation dans un même flux d'information et que lui adjoindre de nouvelles fonctions revenait à le complexifier fortement.
L'idée est donc venue de séparer les deux éléments : la présentation, à l'aide de feuilles de style (XSL : eXtended Style Language) et d'un autre côté les données et leur structuration et relations.
Ainsi, à un document XML on applique la feuille de style XSL et l'on peut voir les données présentées dans la forme, l'imbrication et la structuration que l'on veut. Mieux, l'application de feuilles de style de type CSS (Cascading Style Sheets) permet de transformer les flux de données XML en données structurées et présentées sous forme de flux HTML directement lisible dans n'importe quel navigateur web.
A l'origine de XML on trouve le langage SGML (Structured, Generalized Markup Language) utilisé notamment pour la documentation technique et principalement dans le domaine de la recherche scientifique.
En fait XML est un langage de description de structures de document. Sa puissance est considérable et d'autant plus spectaculaire qu'il s'avère être d'une grande simplicité. Il sert aussi bien au stockage des données qu'à leur recherche, et par conséquent il s'avère très à l'aise dans l'échange de message.

Allier puissance et simplicité est une gageure réussie dans XML par une cuisine simple : décomposer chaque rôle par un document spécifique. En fait un document XML est composé de deux éléments indissociables : le flux de données (XML) et la grammaire (DTD : Document Type Definition), c'est à dire les règles syntaxiques applicable au document. C'est un peu comme si l'on dissociait dans un programme informatique les données du langage et que l'on fournissait un nouveau langage et ses possibilités d'utilisation à chaque exécution. Un tel mécanisme peut sembler lourd, mais il faut comprendre qu'il existe une DTD de base pouvant servir de trame à toutes les données non spécifiques.
A contrario, on construira des DTD spécifiques pour dialoguer de manière plus précise, en fonctions de règles "métiers" comme celles que l'on va trouver dans l'industrie chimique, l'univers de la finance ou les sciences mathématiques.
Aujourd'hui d'important sites Internet (rosettanet, oasis, mtic...) permettent de publier des documents XML valide et les DTD afin que les opérateurs informatiques œuvrant dans ces métiers puissent communiquer plus facilement des informations de manière automatique.
D'un autre côté de nouveaux produits, mettant en œuvre XML, sont publiés chez les éditeurs de logiciels et sont destinés à faciliter l'échange de données informatique (EDI). C'est par exemple le cas du serveur BizTalk de Microsoft.

Les avantages de XML sont donc immenses...

XML :

- permet de structurer facilement les données

- est prévu pour gérer des relations entre les données d'un même document

- facilite grandement l'échange de données informatique

Par conséquent XML à tendance à devenir le standard de la conversation des données entre les systèmes informatiques.

Par exemple, avec XML il est maintenant plus facile de répliquer les données d'une base à l'autre même si les bases n'ont pas les mêmes structures, et même si les SGBDR sont différents.

Voici deux exemples d'utilisation de XML.
Le premier permet de définir des types de données. C'est 'équivalent de l'ordre SQL "CREATE DOMAIN" :

<datatype name = "ref_produit" source = "string">
pattern value = "\d(5)-\d(5)"
</datatype>

<datatype name = "temperature" source = "integer">
<minInclusive>-272</minInclusive>
<maxInclusive>10000</maxInclusive>
</datatype>

Le second, permet d'envoyer dans une URL, un ordre SELECT directement à une base de données :

SELECT+CLI_NOM,+CLI_PRENOM+FROM+t_CLIENT+FOR+XML+AUTO

Le signe plus étant converti en espace et les mots clef "FOR XML AUTO" demande à ce que le serveur de base de données renvoie le flux d'information en réponse, directement sous forme XML.

De nombreux SGBDR commencent à travailler au format XML. C'est le cas de SQL Server 2000 de Microsoft mais aussi de Informix, DB2 (IBM) et d'Oracle. Des ateliers complets commencent à voir le jour, avec la base de données et les outils de développement capable de générer les interfaces web. C'est le cas des produits XDBMS de XML-centric, Excelon XML Data Server d'Object Design Inc. ou encore de Tamino et sa suite de Software AG.

2-2 - eXtended Query Language (XQL)

Mais l'avenir de SQL s'intitule XQL (eXtended Query Language) que l'on peut raisonnablement qualifier de langage d'interrogation de données structurées sous XML !

Voici un exemple de document XML :

<?xml version="1.0"?>
<auteur>
<prenom>Victor</prenom>
<nom>HUGO</nom>
<oeuvre genre="roman">
<titre>Les Misérables</titre>
<publication>1861-11-17</publication>
</oeuvre>
<oeuvre genre="roman">
<titre>Notre Dame de Paris</titre>
<publication>1831-02-27</publication>
</oeuvre>
</auteur>
<auteur>
<nom>VOLTAIRE</nom>
<oeuvre genre="nouvelle">
<titre>Zadig ou la Destinée</titre>
</oeuvre>
<oeuvre genre="usuel">
<titre>Dictionnaire Philosophique</titre>
<publication>1764-11-26</publication>
</oeuvre>
<oeuvre genre="roman">
<titre>Candide</titre>
</oeuvre>
<oeuvre genre="essais">
<titre>Traité sur la Tolérance</titre>
<publication>1763-01-06</publication>
</oeuvre>
</auteur>

Son contenu est une véritable base de données et sa structure ressemble à une arborescence.

auteur
|>prenom
|>nom
|>oeuvre
|>titre
|>publication

Voici quelques requêtes XQL utilisant l'exemple ci dessus :

Rechercher toutes les oeuvres :
Requête XQL :

//oeuvre

Réponse :

<xql:result>
<oeuvre genre="roman">
<titre>Les Misérables</titre>
<publication>1861-11-17</publication>
</oeuvre>
<oeuvre genre="roman">
<titre>Notre Dame de Paris</titre>
<publication>1831-02-27</publication>
</oeuvre>
<oeuvre genre="nouvelle">
<titre>Zadig ou la Destinée</titre>
</oeuvre>
<oeuvre genre="usuel">
<titre>Dictionnaire Philosophique</titre>
<publication>1764-11-26</publication>
</oeuvre>
<oeuvre genre="roman">
<titre>Candide</titre>
</oeuvre>
<oeuvre genre="essais">
<titre>Traité sur la Tolérance</titre>
<publication>1763-01-06</publication>
</oeuvre>
</xql:result>

Rechercher les auteurs dont le prénom est Victor
Requête XQL :

//auteur[prenom = 'Victor']

Réponse :

<xql:result>
<auteur>
<prenom>Victor</prenom>
<nom>HUGO</nom>
<oeuvre genre="roman">
<titre>Les Misérables</titre>
<publication>1861-11-17</publication>
</oeuvre>
<oeuvre genre="roman">
<titre>Notre Dame de Paris</titre>
<publication>1831-02-27</publication>
</oeuvre>
</auteur>
</xql:result>

Rechercher toutes les oeuvres publiées entre 1764 et 1835 :
Requête XQL :

//oeuvre[publication >= date("1764-01-01")
$and$ publication <= date("1835-12-31")]

Réponse :

<xql:result>
<oeuvre genre="roman">
<titre>Les Misérables</titre>
<publication>1861-11-17</publication>
</oeuvre>
<oeuvre genre="usuel">
<titre>Dictionnaire Philosophique</titre>
<publication>1764-11-26</publication>
</oeuvre>
</xql:result>

Bien entendu ces réponses brutes nécessitent l'application d'une feuille de style XLS pour être débarrassées de tout les éléments propres à la cuisine XML.

Tout d'un coup, XQL ne vous paraît-il pas encore plus simple que SQL ?