Préambule▲
NOTA : La structure de la base de données exemple, ainsi qu'une version des principales bases utilisées sont disponibles dans la page « La base de données exemple ».
Sans doute, allez-vous immédiatement vous intéresser à la syntaxe du CREATE TABLE. C'est pour cela, sans doute, que vous êtes tombé sur cette page… Je vous plains, car vous allez tout droit créer des bases de données boiteuses et rapidement impossibles à maintenir. Si j'avais un conseil à vous donner ce serait le suivant : lisez les paragraphes 2 à 4 avant même de vous plonger, tête baissée dans la création des tables. Il y a tant de choses qui vous faciliteront la vie que je gage que vous m'en serez éternellement reconnaissant…
1. Règles de nommage▲
La norme SQL 2 impose un certain nombre de règles concernant les noms des objets d'une base de données.
Un nom d'objet (table, colonne, contrainte, vue…) doit avoir les caractéristiques suivantes :
- ne pas dépasser 128 caractères ;
- commencer par une lettre ;
- comprendre uniquement les caractères suivants [ 'A' .. 'Z'] U ['a' .. 'z'] U [ '0' .. '1'] U [ '_' ] ;
- un nom d'objet ne peut pas être un mot réservé de SQL sauf à être utilisé avec des guillemets ;
- être insensible à la casse.
Voici quelques identifiants normatifs et non…
Exemple 1
VALABLE |
INTERDIT |
---|---|
Sélectionnez
|
Sélectionnez
|
ATTENTION : un nom d'objet doit être unique au sein de l'objet qui le contient. Par exemple un nom de table ou de vue doit être unique au sein de la base, un nom de colonne doit être unique au sein de la table ou la vue, etc.
2. Au début était le néant…▲
C'est toujours la même histoire… Comment créer une base de données ? En se connectant au serveur de bases de données ! Mais comment se connecter au serveur de base de données ? En créant une base de données dotée au moins d'une connexion et d'un utilisateur avec les privilèges adéquats… Bref, nous entrons de plein front dans le célèbre problème de l'œuf et de la poule…
Heureusement la plupart du temps, les fournisseurs de SGBDR pourvoient leur engin avec un utilisateur, son mot de passe et un certain nombre de bases de données précréés afin de nous faciliter la vie.
Par exemple sur InterBase le nom d'utilisateur et son mot de passe sont « SYSDBA/masterkey ». Sur MS SQL Server, le nom d'utilisateur est « sa » sans mot de passe (et je vous conseille vivement d'en mettre un immédiatement). Sur Oracle, c'est « System/manager » ou bien « Sys/change_on_install ». Sur DB2 c'est « db2admin ». Sur Informix un compte « informix » est créé dans le groupe « informix-admin ». Sous mySQL c'est « mysqladm » qu'il faut utiliser… Ingres est plus restrictif puisqu'il impose à l'utilisateur de donner expressément un nom lors de l'installation. Pour Sybase et ses deux bases, des différences : ASE veut « sa » sans mot de passe, tandis que ASA impose « DBA/SQL » !
En fait tous ces « comptes » sont des connexions au serveur et la plupart du temps correspondent à la fois à la notion de connexion et d'utilisateur. Mais la norme SQL fait une différence entre le concept de connexion et celui d'utilisateur.
2-1. La connexion▲
Pour SQL 2, la connexion à un SGBDR prend la syntaxe suivante :
CONNECT
TO
{DEFAULT
|
nom_serveur [AS surnom_serveur ]
[USER nom_utilisateur]
}
Par exemple l'ordre :
Exemple 2
CONNECT
TO
DEFAULT
Se connecte au serveur de base de données défini par défaut. La plupart du temps un serveur de bases de données est installé sur une machine dédiée, ce qui fait qu'il n'y a pas d'ambiguïté. En revanche, si plusieurs serveurs sont installés sur la même machine, il faut nommer le serveur.
Exemple 3
CONNECT
TO
MON_SERVEUR
Se connecte au serveur identifié « MON_SERVEUR ».
Il est même possible de renommer ce serveur :
Exemple 4
CONNECT
TO
MON_SERVEUR AS
SRV1
Qui se connecte à « MON_SERVEUR », mais le surnomme SRV1. Dès lors ce nouveau nom pourra être utilisé dans divers ordres SQL en lieu et place du nom authentique du serveur.
Enfin, il est possible de préciser le nom de l'utilisateur (qui doit exister dans le SGBDR) qui sera associé à la connexion. Sans cette précision, le SGBDR emprunte le nom par défaut implanté par le constructeur.
Exemple 5
CONNECT
TO
MON_SERVEUR USER
FRED_BROUARD
Se connecte au serveur « MON_SERVEUR » en empruntant l'identité FRED_BROUARD comme utilisateur.
Vous l'aurez compris, à une connexion est toujours associée un nom d'utilisateur. Petite précision, un utilisateur SQL est un objet du serveur (ou de la base de données dans certains cas) et se définit aussi par un ordre SQL…
NOTA : la plupart du temps, ce mécanisme est masqué par une interface graphique, ou encore par l'imbrication du serveur de bases de données et de son OS. Par exemple pour SQL Server de Microsoft, cet ordre de connexion s'effectue derrière la boîte de dialogue suivante :
Pour InterBase, c'est la boîte de dialogue suivante qui fait office :
Mais si vous désirez passer des ordres SQL InterBase en vous connectant à une base spécifique et ceci depuis une commande du shell, vous pouvez lancer l'ordre suivant :
Exemple 6 (Interbase)
CONNECT
"chemin_vers_fichier_base"
USER
"nom_utilisateur"
PASSWORD
"mot_de_passe"
La norme SQL propose en outre la possibilité de basculer d'une connexion à l'autre (à condition que l'autre existe et soit dormante à l'aide de l'ordre :
SET
CONNECTION
{ DEFAULT
|
nom_session }
Où nom_session représente une connexion déjà établie et dormante (c'est-à-dire une connexion ouverte, mais qui n'est pas activée par le passage d'ordre SQL…).
Bien entendu il est possible de fermer une connexion en utilisant l'ordre SQL DISCONNECT :
DISCONNECT { DEFAULT
|
CURRENT
|
ALL
|
nom_session}
La lecture de cette syntaxe laisse bien peu d'interprétation et je laisse donc à votre sagacité le soin de comprendre à quoi peuvent bien faire penser de tels mots clefs !
2-2. La session▲
Là nous entrons déjà dans une notion plus complète et donc, forcément plus complexe…
Une session au sens de la norme SQL est une connexion activée et possède certains attributs particuliers. Les attributs d'une session sont :
- un identifiant d'autorisation (AUTHORIZATION) ;
- un nom de catalogue (CATALOG) ;
- un nom de schéma (SCHEMA) ;
- un fuseau horaire (TIME ZONE) ;
- un jeu de caractères (CHARACTER SET).
L'identifiant d'autorisation doit impérativement être choisi parmi les mots clefs suivants USER, CURRENT_USER, SESSION_USER et SYSTEM_USER ou bien en donnant un nom d'utilisateur spécifique.
Un catalogue (CATALOG est le mot clef SQL) est une collection de bases de données et peut soit prendre la forme d'un serveur, d'un groupe de serveurs ou bien de « répertoires » de bases de données.
Un schéma n'est autre qu'une base de données, c'est-à-dire son nom. La norme SQL les appelle SCHEMA parce qu'une base de données doit être décrite pour être utilisée, et son architecture (tables, colonnes, vues…) correspond à un modèle de données physique.
Un fuseau horaire (TIME ZONE) n'est autre que l'indication du décalage de l'heure locale par rapport au temps universel (ou UTC Unified Time Coordination). C'est ainsi qu'il permet de gérer les décalages horaires de toutes les zones locales de la planète ce qui est bien pratique lorsque l'on veut développer une application internationale, notamment pour les sites web !
Enfin, le jeu de caractères (CHARACTER SET) permet de définir quel sous-ensemble de symboles est utilisé pour les 256 combinaisons de deux octets qui correspondent à la frappe des caractères. N'oublions pas que même en Europe les jeux de caractères ne sont pas les mêmes d'une nation à l'autre. Par exemple l'alphabet finois ou le tchèque sont dotés de curieux petits accents en forme de cercle ou de croissant, tandis que dans le cyrillique c'est la forme même des lettres qui change… et tout de même, ces gens-là doivent pouvoir s'exprimer ! (notons que le français possède un certain nombre de caractères particuliers comme le « c » avec ça cédille ou l'« e » dans l'« o », présent par exemple dans le mot cœur).
2-3. Catalogues et shémas▲
Comme nous venons de le définir, le terme CATALOG permet de définir une collection de bases de données. Il est très différemment implémenté dans les divers SGBDR que proposent les éditeurs. Pour SQL Server la notion de CATALOG se confond avec celle de base de données, tandis que la notion de schéma se confond avec celle de propriétaire. Par exemple en demandant à la machine de nous fournir la liste des bases de données avec la requête suivante, voici ce que le serveur nous propose :
Exemple 7 (SQL Server)
Sélectionnez
|
Sélectionnez
|
3. Créer une nouvelle base de données▲
Vous trouverez des compléments d'information sur le sujet aux pages 190 à 192 de l'ouvrage « SQL », collection « La Référence », Campus Press éditeur.
Évidemment ce qui vous intéresse le plus c'est d'abord de créer une base de données. C'est-à-dire un SCHEMA !
La norme SQL propose l'ordre de création d'une base de données (pardon, d'un schéma) suivant :
CREATE
SCHEMA
[ nom_schema ]
[ AUTHORIZATION utilisateur ]
[ DEFAULT CHARACTER SET jeu_de_caractères ]
[ liste_des_objets_du_schéma ]
La liste des objets du schéma n'étant autre que la création des éléments de la base.
Je ne m'étendrai pas sur cette syntaxe ni sur l'ordre SQL 2 de suppression des schémas :
DROP
SCHEMA
[ nom_schema ]
{ RESTRICT
|
CASCADE
}
car ces ordres sont très rarement implémentés tels quels dans les SGBDR. En revanche on trouve la plupart du temps un pseudo-ordre SQL « CREATE DATABASE » fort pratique, mais qui n'existe nulle part dans la norme !
Mais si j'ai tenu à vous montrer ceci, c'est que, par défaut, une connexion ou un serveur possède des attributs. Les méconnaitre et notamment en méconnaitre le paramétrage peut vous causer les pires ennuis. C'est pourquoi je vous propose de réfléchir sur trois questions fondamentales :
- Quel est l'ordre de tri de mes données littérales ?
- Comment s'effectue la comparaison entre colonnes contenant des chaînes de caractères notamment si ces dernières sont de types différents (VARCHAR et CHAR en particulier) ?
- Quelle est à tout moment l'heure et la date procurée par le SGBDR et cette heure est-elle modifiée en fonction des saisons ???
Si vous n'avez pas réfléchi à ces problèmes fondamentaux, vous risquez quelques problèmes difficilement surmontables…
Par exemple :
- Comment faire correspondre l'ordre de mes données entre un tableau trié par une routine en C++, Java ou Delphi et le serveur de base de données ?
- Comment faire en sorte de distinguer les deux références suivantes « GFY-12-aj » et « gfy-12-AJ » dans un SELECT si le serveur a été paramétré pour être rendu insensible à la casse ??
- Comment compter exactement la durée d'une intervention technique en heures si entre la déclaration de la panne et la résolution du problème est intervenu un changement d'horaire du fait de l'heure d'été ???
Je ne m'étendrai donc pas plus sur le sujet, car il est assez spécifique aux différents SGBDR de chaque éditeur. Pensez simplement que l'installation par défaut du serveur prôné avec un gadget qui le rend insensible à la casse est une aberration. En effet, autant il est facile de formater des données pour que la comparaison et même la saisie se fassent au bon format, autant lorsque cette insensibilité est activée, le coût de retour en arrière est exorbitant !
Faites donc le test suivant. Créez dans votre base de données la table et les données suivantes :
Exemple 8
CREATE
TABLE
TEST
(
MOT VARCHAR
(
16
))
INSERT
INTO
TEST VALUES
(
'Électricité'
)
INSERT
INTO
TEST VALUES
(
'électricité'
)
INSERT
INTO
TEST VALUES
(
'ELECTRICITE'
)
INSERT
INTO
TEST VALUES
(
'electricite'
)
INSERT
INTO
TEST VALUES
(
'electron'
)
INSERT
INTO
TEST VALUES
(
'electeur'
)
INSERT
INTO
TEST VALUES
(
'électeur'
)
Exécutez donc les requêtes de test suivantes :
Exemple 9
SELECT
MOT
FROM
TEST
WHERE
MOT =
'electricite'
En principe vous devriez n'avoir qu'une seule occurrence…
Exemple 10
SELECT
MOT
FROM
TEST
ORDER
BY
MOT
Là, le folklore est en place !
Puis créez dans votre langage favori un tableau de chaînes de caractères et avec une routine de tri de votre cru, triez-le et comparez les résultats…
Vous êtes horrifié ? Bien fait !… Vous auriez dû me lire avant de vous lancer dans la conception des bases de données relationnelles !!!
Voici ce test effectué sous différentes bases de données :
Sélectionnez
|
Sélectionnez
|
|
Sous MS SQL Server 7, paramétrage par défaut |
Sélectionnez
|
Sélectionnez
|
Sous PostGreSQL 7.1.2, paramétrage par défaut |
Sélectionnez
|
Sélectionnez
|
Sous InterBase 5.5, paramétrage par défaut |
Sélectionnez
|
Sélectionnez
|
Sous paradox 9, paramétrage par défaut |
Sélectionnez
|
Sélectionnez
|
MySQL 3.23.37, paramétrage par défaut |
Sélectionnez
|
Sélectionnez
|
4. Une question de caractères…▲
4-1. Jeu de caractères▲
Je vais encore vous embêter avec un concept qui, la plupart du temps est ignoré ou passé sous silence, mais qui permet de se sauver de situations inextricables portant sur la comparaison des littéraux. La norme SQL a prévu, outre le jeu de caractères, l'utilisation de séquences de collation. Même si elles ne sont pas encore parfaitement implantées telles que la norme SQL 2 l'a prévu, il est rare qu'un mécanisme similaire ne soit pas fourni dans votre SGBDR.
Le jeu de caractères consiste en une correspondance des 256 ou 65536 caractères par rapport aux symboles graphiques représentés.
256 correspond au type CHAR et VARCHAR et 65536 aux types NATIONAL CHAR ou NATIONAL VARCHAR. La plupart du temps nous utilisons sans le savoir un jeu de caractères basique établi par défaut dans la version locale de l'OS.
Voici par exemple les jeux de caractères disponibles dans les créations de tables de Paradox :
Exemple 11
ANSI 1250 |
tchèque, hongrois polonais, slovène |
ANSI 1251 |
cyrillique et bulgare |
ANSI 1252 |
nordique, espagnol, suédois, finlandais |
ANSI 1253 |
grec |
ANSI 1254 |
turc |
ANSI 1255 |
binaire |
DOS 437 |
Europe de l'Ouest, suédois, finlandais, espagnol |
DOS 737 |
grec |
DOS 850 |
brésilien, portugais, canadien, français |
DOS 852 |
tchèque, hongrois polonais, slovène |
DOS 857 |
turc |
DOS 861 |
islandais |
DOS 862 |
binaire |
DOS 865 |
norvégien, danois |
DOS 866 |
cyrillique |
DOS 867 |
tchèque |
DOS 868 |
bulgare |
DOS 874 |
thaïlandais |
DOS 932 |
japonais |
DOS 936 |
chinois |
DOS 949 |
coréen |
DOS 950 |
tawainais |
Notez qu'ils sont décomposés en deux familles, celle du DOS (la table des caractères de base n'étant pas normalisée, mais propre à l'inventeur du système d'exploitation DOS…) et celle de l'ANSI (relatif à Windows qui se base sur la norme ANSI - American National Standard Institute).
On parle souvent de table ASCII. L'ASCII a été créé par BEMMER en 1965 , produit par le groupe de travail X3.4 de l'ANSI, certifié en 1977 et adopté par l'ISO en 1968 sous le n° 646 [f2s]. Ce ne sont en fait que les 128 premiers caractères du fait du codage à l'origine sur 7 bits. Lorsque le codage des caractères a été étendu par nécessité à 8 bits, des déclinaisons de cette table ont été possibles pour régler le problème des caractères diacritiques (accents, cédilles, caractères spéciaux tels que le double ss allemand).
Rassurez-vous l'ISO (International Standard Organisation) s'en est mêlé et propose des jeux de caractères plus cohérents. Voici par exemple la table iso8859-1, actuellement la plus répandue et la plus utilisée notamment sur le NET :
Exemple 12
iso8859-1 character table and corresponding HTML code
Description Code Charactèr name
=================================== ============ ==============
guillemet " --> " " --> "
et commercial & --> & & --> &
signe plus petit que < --> < < --> <
greater-than sign > --> > > --> >
Description Char Code Entity name
=================================== ==== ============ ==============
espace non sécable   --> -->
exclamation inverse ¡ ¡ --> ¡ ¡ --> ¡
centimes ¢ ¢ --> ¢ ¢ --> ¢
livre sterling £ £ --> £ £ --> £
symbole monétère général ¤ ¤ --> ¤ ¤ --> ¤
symbole du yen ¥ ¥ --> ¥ ¥ --> ¥
barre verticale brisée ¦ ¦ --> ¦ ¦ --> ¦
&brkbar; --> &brkbar;
paragraphe § § --> § § --> §
umlaut (dieresis) ¨ ¨ --> ¨ ¨ --> ¨
¨ --> ¨
copyright © © --> © © --> ©
feminine ordinal ª ª --> ª ª --> ª
guillement gauche « « --> « « --> «
not sign ¬ ¬ --> ¬ ¬ --> ¬
soft hyphen ­ --> ­ -->
registered trademark ® ® --> ® ® --> ®
macron accent ¯ ¯ --> ¯ ¯ --> ¯
&hibar; --> &hibar;
signe des degrés ° ° --> ° ° --> °
plus ou moins ± ± --> ± ± --> ±
puissance carrée ² ² --> ² ² --> ²
puissance cubique ³ ³ --> ³ ³ --> ³
accent aigu ´ ´ --> ´ ´ --> ´
symbole micro µ µ --> µ µ --> µ
symbole de paragraphe ¶ ¶ --> ¶ ¶ --> ¶
point central · · --> · · --> ·
cédille ¸ ¸ --> ¸ ¸ --> ¸
exposant un ¹ ¹ --> ¹ ¹ --> ¹
masculine ordinal º º --> º º --> º
guillement droit » » --> » » --> »
un quart (fraction) ¼ ¼ --> ¼ ¼ --> ¼
un demi (fraction) ½ ½ --> ½ ½ --> ½
trois quart (fraction) ¾ ¾ --> ¾ ¾ --> ¾
point d'interrogation inversé ¿ ¿ --> ¿ ¿ --> ¿
A accent grave (majuscule) À À --> À À --> À
A accent aigu (majuscule) Á Á --> Á Á --> Á
A accent circonflexe (majuscule) Â Â --> Â Â --> Â
A tilde (majuscule) Ã Ã --> Ã Ã --> Ã
capital A, dieresis or umlaut mark Ä Ä --> Ä Ä --> Ä
capital A, ring Å Å --> Å Å --> Å
capital AE diphthong (ligature) Æ Æ --> Æ Æ --> Æ
capital C, cedilla Ç Ç --> Ç Ç --> Ç
capital E, grave accent È È --> È È --> È
capital E, acute accent É É --> É É --> É
capital E, circumflex accent Ê Ê --> Ê Ê --> Ê
capital E, dieresis or umlaut mark Ë Ë --> Ë Ë --> Ë
capital I, grave accent Ì Ì --> Ì Ì --> Ì
capital I, acute accent Í Í --> Í Í --> Í
capital I, circumflex accent Î Î --> Î Î --> Î
capital I, dieresis or umlaut mark Ï Ï --> Ï Ï --> Ï
capital Eth, Icelandic Ð Ð --> Ð Ð --> Ð
Đ --> Đ
capital N, tilde Ñ Ñ --> Ñ Ñ --> Ñ
capital O, grave accent Ò Ò --> Ò Ò --> Ò
capital O, acute accent Ó Ó --> Ó Ó --> Ó
capital O, circumflex accent Ô Ô --> Ô Ô --> Ô
capital O, tilde Õ Õ --> Õ Õ --> Õ
capital O, dieresis or umlaut mark Ö Ö --> Ö Ö --> Ö
multiply sign × × --> × × --> ×
capital O, slash Ø Ø --> Ø Ø --> Ø
capital U, grave accent Ù Ù --> Ù Ù --> Ù
capital U, acute accent Ú Ú --> Ú Ú --> Ú
capital U, circumflex accent Û Û --> Û Û --> Û
capital U, dieresis or umlaut mark Ü Ü --> Ü Ü --> Ü
capital Y, acute accent Ý Ý --> Ý Ý --> Ý
capital THORN, Icelandic Þ Þ --> Þ Þ --> Þ
small sharp s, German (sz ligature) ß ß --> ß ß --> ß
small a, grave accent à à --> à à --> à
small a, acute accent á á --> á á --> á
small a, circumflex accent â â --> â â --> â
small a, tilde ã ã --> ã ã --> ã
small a, dieresis or umlaut mark ä ä --> ä ä --> ä
small a, ring å å --> å å --> å
small ae diphthong (ligature) æ æ --> æ æ --> æ
small c, cedilla ç ç --> ç ç --> ç
small e, grave accent è è --> è è --> è
small e, acute accent é é --> é é --> é
small e, circumflex accent ê ê --> ê ê --> ê
small e, dieresis or umlaut mark ë ë --> ë ë --> ë
small i, grave accent ì ì --> ì ì --> ì
small i, acute accent í í --> í í --> í
small i, circumflex accent î î --> î î --> î
small i, dieresis or umlaut mark ï ï --> ï ï --> ï
small eth, Icelandic ð ð --> ð ð --> ð
small n, tilde ñ ñ --> ñ ñ --> ñ
small o, grave accent ò ò --> ò ò --> ò
small o, acute accent ó ó --> ó ó --> ó
small o, circumflex accent ô ô --> ô ô --> ô
small o, tilde õ õ --> õ õ --> õ
small o, dieresis or umlaut mark ö ö --> ö ö --> ö
division sign ÷ ÷ --> ÷ ÷ --> ÷
small o, slash ø ø --> ø ø --> ø
small u, grave accent ù ù --> ù ù --> ù
small u, acute accent ú ú --> ú ú --> ú
small u, circumflex accent û û --> û û --> û
small u, dieresis or umlaut mark ü ü --> ü ü --> ü
small y, acute accent ý ý --> ý ý --> ý
small thorn, Icelandic þ þ --> þ þ --> þ
small y, dieresis or umlaut mark ÿ ÿ --> ÿ ÿ --> ÿ
On trouvera diverses informations sur le sujet dans les pages web suivantes :
http://alis.isoc.org/codage/iso8859/jeuxiso.htm
http://www.ping.be/~ping9985/html/iso8859-.htm
http://www.w3.org/MarkUp/html-spec/html-spec_9.html#SEC9.7.2
Autrement dit, le jeu de caractères restreint à 256 symboles ASCII les possibilités de combiner les lettres, signes de ponctuation et autres caractères particuliers imprimables.
4-2. Collation et « translation »▲
La séquence de collation est un complément indispensable du jeu de caractères et permet de définir non seulement la position ordinale de chaque caractère, mais leur éventuelle « confusion » ! Hé oui, comment pensez-vous que la machine puisse devenir insensible à la casse et aux accents sans un tel mécanisme ?
C'est ainsi que différentes séquences de collation sont possibles sur un même jeu de caractères.
Voici par exemple les séquences de collation des différents jeux de caractères de Paradox :
Exemple 12
Jeu de caractères |
Classement des caractères |
---|---|
1250 (ANSI) |
Compatible avec Paradox « czech » (niveau 2) |
1251 (ANSI) |
Compatible avec Paradox « cyrr » (2-level) |
1252 (ANSI) |
Compatible avec Paradox « intl » (niveau 3) |
1253 (ANSI) |
Compatible avec Paradox « greek » (niveau 2) |
1254 (ANSI) |
Compatible avec Paradox « turk » (niveau 2) |
1255 (ANSI) |
Binaire |
DOS CODE PAGE 437 |
Binaire |
DOS CODE PAGE 737 |
Greek (niveau 2) |
DOS CODE PAGE 850 |
Brazilian Portuguese, French Canadian |
DOS CODE PAGE 852 |
Czech852 (niveau 2) |
DOS CODE PAGE 857 |
Turkish (niveau 2) |
DOS CODE PAGE 861 |
Icelandic (niveau 2) |
DOS CODE PAGE 862 |
Binaire |
DOS CODE PAGE 865 |
Norwegian/Danish (Paradox 3.5) |
DOS CODE PAGE 866 |
Cyrillic |
DOS CODE PAGE 867 |
Czech867 (niveau 2) |
DOS CODE PAGE 868 |
Bulgaria (niveau 2) |
DOS CODE PAGE 874 |
Thai (niveau 3) |
DOS CODE PAGE 932 |
Japanese |
DOS CODE PAGE 936 |
China (niveau 1) |
DOS CODE PAGE 949 |
Korea (niveau 1) |
DOS CODE PAGE 950 |
Taiwan (niveau 1) |
Par exemple dans la séquence de collation ISO 1252 spanish, le « ñ » (« n » avec tilde) sera confondu avec le caractère « n » lors des comparaisons partielles…
Pour InterBase par exemple, les jeux de caractères disponibles sont les suivants :
Exemple 14
Sélectionnez
|
Sélectionnez
|
Auxquels sont associées les séquences de collations suivantes :
Exemple 15
Sélectionnez
|
Sélectionnez
|
Comment cela se passe à l'intérieur et à quoi cela correspond-il ? Jetons un coup d'œil à la procédure stockée sp_helpsort de MS SQL Server et tout va devenir plus lumineux…
Exemple 15
Sélectionnez
|
Sélectionnez
|
Comme on le voit, l'ordre de chacun des caractères est établi par la séquence, mais comme cette séquence de collation est rendue insensible à la casse, il y a confusion entre les majuscules et les minuscules…
Autrement dit, l'ordre de tri, comme la correspondance des recherches que l'on effectuera dans des requêtes SQL sera prédéfini par la séquence de collation. La méconnaitre et méconnaitre les possibilités de paramétrage de son SGBDR à ce niveau, c'est laisser faire Microsoft, Oracle ou Borland, comme il l'entend et non comme vous voulez que ce soit et rejaillira tôt ou tard comme problématique dans la mise au point de vos applications…
Sachez qu'en général, une séquence de collation par défaut est proposée lors de l'installation de votre serveur, et que sur certains SGBDR on peut modifier la séquence de collation pour la table entière ou encore pour une colonne seulement.
Bien entendu la norme SQL 2 a codifié et pensé cela depuis fort longtemps et propose même des mécanismes de traduction afin de faire correspondre des données venant de jeux et collations différentes, mais ces possibilités sont encore trop rares à être implémentées au sein des SGBDR des différents éditeurs. Ainsi SQL 2 a défini les CREATE CHARACTER SET et CREATE COLLATION afin de répondre à toutes les attentes. Malheureusement la plupart du temps il n'est possible d'utiliser que les jeux et collations prédéfinis par l'éditeur du SGBDR.
Par exemple Microsoft dans la version 7 de sa base de données SQL Server était très en retard sur le sujet. Un seul jeu de caractères et une seule séquence de collation pouvaient être utilisés au sein du serveur ! Comme le serveur était mono-instance, il fallait autant de serveurs (machines) que d'applications pour les différents pays d'exploitation de la base de données, ce qui rendait SQL Server difficile comme choix pour des applications Internet internationales, sauf à utiliser quelques « trucs » et « bouts de ficelles » à base d'UNICODE… En revanche, de ce côté, un modeste serveur comme InterBase était fort bien pensé !
Par exemple pour InterBase, lors de la création d'une base de données, on peut préciser le jeu de caractères :
Exemple 17
CREATE
DATABASE
'production.gdb'
DEFAULT
CHARACTER
SET
'ISO8859_1'
On peut aussi le faire pour chaque colonne dans la création de table :
Exemple 18
CREATE
TABLE
TEST_CHAR_SET
(
COL1 CHAR
(
32
)
CHARACTER
SET
ASCII
,
COL2 CHAR
(
32
)
CHARACTER
SET
DOS437,
COL3 CHAR
(
32
)
CHARACTER
SET
DOS850)
Et préciser en outre la collation utilisée :
Exemple 19
CREATE
TABLE
TEST_COLLATION
(
COL1 CHAR
(
32
)
CHARACTER
SET
ISO8859_1 COLLATE
FR_FR,
COL2 CHAR
(
32
)
CHARACTER
SET
ISO8859_1 COLLATE
ISO8859_1)
Mais attention, pas question de rentrer n'importe quoi dans la table, le serveur veille en général à la correspondance des jeux dans les entrées/sortie de flux d'informations (requêtes et ensemble de résultats).
Ainsi en alimentant la table TEST_COLLATION avec les mêmes données pour les deux colonnes…
Exemple 20
INSERT
INTO
TEST_COLLATION VALUES
(
'Électricité'
, 'Électricité'
)
INSERT
INTO
TEST_COLLATION VALUES
(
'électricité'
, 'électricité'
)
INSERT
INTO
TEST_COLLATION VALUES
(
'ELECTRICITE'
, 'ELECTRICITE'
)
INSERT
INTO
TEST_COLLATION VALUES
(
'electricite'
, 'electricite'
)
INSERT
INTO
TEST_COLLATION VALUES
(
'electron'
, 'electron'
)
INSERT
INTO
TEST_COLLATION VALUES
(
'electeur'
, 'electeur'
)
INSERT
INTO
TEST_COLLATION VALUES
(
'électeur'
, 'électeur'
)
…nous n'obtiendrons pas le même ordre de tri :
Exemples 21 et 22
Sélectionnez
|
Sélectionnez
|
Sélectionnez
|
Sélectionnez
|
NOTA : pour pouvoir utiliser ce jeu d'essais dans votre interface de requêtage vous devez préalablement indiquer au serveur quand vous utilisez le jeu de caractères ISO8859_1 en utilisant la commande SET NAMES d'InterBase ou le paramétrage avancé.
Bien entendu, on peut forcer une séquence de collations dans un select à des fins de comparaison ou de tri. Pour cela il faut utiliser le mot clef COLLATE et donner le nom de la collation de travail :
Exemples 23 et 24
Sélectionnez
|
Sélectionnez
|
Sélectionnez
|
Sélectionnez
|
C'est pourquoi on ne le répétera jamais assez, ce paramétrage entre jeu de caractères et séquence de collation est délicat et obéit souvent à des mécanismes souvent peu normatifs.
NOTA : Peter GULUTZAN a écrit deux bons articles sur la problématique des séquences de collation que l'on trouvera sur le site de dbazine.com à l'url :
http://dbazine.com/gulutzen1.html
http://dbazine.com/gulutzen1a.html
Enfin, je ne saurais trop vous recommander, dans la mesure où vous le pouvez, de paramétrer votre base de données de la manière suivante :
- jeu de caractères ISO8859-1 ;
- sensible à la casse (donc différences entre majuscules et minuscules) ;
- sensible aux accents et autres caractères diacritiques.
En effet, on peut toujours jouer sur les séquences de collation pour redéfinir l'ordre de tri et utiliser des fonctions de conversion telles que UPPER ou LOWER pour insensibiliser la casse, ou encore des fonctions avancées telles que la fonction TRANSLATION proposée par ORACLE pour s'affranchir des accents et autres caractères diacritiques. N'oubliez pas qu'une séquence de collation complexe (par exemple assimilant les majuscules, minuscules et accents comme équivalents) est forcément couteuse en temps d'exécution et cela rejaillira sur les performances d'accès et de traitement de vos données…
La translation, rarement implémentée consiste à définir un ensemble de correspondances entre caractères. Elle permet de remplacer des caractères par d'autres. Par exemple si nous avons créé une translation nommée REMPLACE_PONCTUATION_ESPACE qui définit que les caractères . , ; : ! ? ' " sont remplacés par un caractère espace, alors l'application de la fonction TRANSLATE avec comme paramètre cet identifiant de translation nous obtiendrons une chaîne de caractères dans laquelle tous les signes de ponctuation mentionnés seront remplacés par des espaces.
Exemples 25
Sélectionnez
|
Sélectionnez
|
4-3. Résumons…▲
La norme prévoit la spécification d'un jeu de caractères à l'aide des ordres :
CREATE
CHARACTER
SET
nom_jeu_caractère
[AS]
GET
nom_jeu_caractère_existant
[COLLATE nom_collation | COLLATION FROM ressource_collation]
DROP
CHARACTER
SET
nom_jeu_caractère
La norme prévoit la spécification d'une collation à l'aide des ordres :
CREATE
COLLATION
nom_collation
FOR
nom_jeu_caractère_existant
FROM
ressource_collation
[ PAD SPACE | NO PAD ]
DROP
COLLATION
nom_collation
Dans les deux cas (CREATE CHARCATER SET et CREATE COLATION), une ressource de collation pouvant elle-même être définie comme :
ressource_collation ::
EXTERNAL
(
'collation_externe'
)
nom_collation
DESC
(
nom_collation)
DEFAULT
TRANSLATION nom_traduction [THEN COLLATION nom_colation]
La norme prévoit la spécification d'une translation à l'aide des ordres :
CREATE
TRANSLATION nom_translation
FOR
jeu_caractere_source
TO
jeu_caractère_cible
FROM
{ EXTERNAL
(
'translation_externe'
)
|
IDENTITY
|
nom_translation }
DROP
TRANSLATION nom_translation
Une collation peut être spécifiée, caractère par caractère à l'aide d'opérateurs de comparaison.
Exemple 26
a=A a=à a=â a=ä b=B c=C c=ç d=D e=E e=é e=è ...
Dans ce cas, les caractères a, A, à auront la position ordinale 1, b ou B la position ordinale 2, etc., et cette séquence de collation sera insensible à la casse et aux caractères diacritiques…
Le jeu de caractères peut se spécifier dans la création de la base de données :
CREATE
SCHEMA
nom_base
...
[DEFAULT CHARACTER SET nom_jeu_caractère]
Enfin, une collation peut être utilisée selon la norme SQL 2 dans une comparaison comme dans la clause de tri d'un ordre SELECT.
NOTA : l'implémentation de ces différents éléments varie fortement d'un éditeur de SGBDR à l'autre. C'est pourquoi je vous invite fortement à lire la documentation de votre SGBDR avant de définir votre base et vos tables.
5. Types de données et domaines▲
Vous trouverez des compléments d'information sur le sujet aux pages 36 à 46 de l'ouvrage « SQL », collection « La Référence », Campus Press éditeur.
Nous avons déjà parlé de ces éléments si vous avez lu le tout premier papier consacré à SQL. Mais comme rien ne vaut un bon rappel, voici ce que sont les domaines et les données de SQL.
5-1. Les types SQL 2▲
La norme SQL 2 propose quatre familles de types de données : les littéraux, les numériques, les binaires et les temporelles, elles-mêmes parfois subdivisées.
Le tableau suivant résume les différents types de données. En vert figurent les types SQL 2 et en blanc les familles et sous-familles :
n précise la longeur associée au type, p la précision (nombre de chiffres significatifs), s les décimales et i1 et i2 la précision de durée parmi YEAR, MONTH, DAY, HOUR, MINUTE, SECOND.
5-1-1. Détails des différents types de données…▲
CHARACTER (n) permet de préciser une donnée littérale (chaîne de caractères) dont les caractères sont codés sur un jeu de type ASCI, EBCDIC ou DOS (2 octets par caractères) de longueur fixe n. Si la donnée à insérer est de taille inférieure, elle est complétée par des blancs significatifs.
Exemple 27
CHARACTER
(
4
)
définit une colonne comportant exactement 4 caractères.
Le synonyme CHAR peut être utilisé.
CHARACTER VARYING (n) permet de préciser une donnée littérale (chaîne de caractères) dont les caractères sont codés sur un jeu de type ASCI, EBCDIC ou DOS de longueur maximale n. Si la donnée à insérer est de taille inférieure elle est compactée et aucun caractère blanc significatif ne la complète.
Exemple 28
CHARACTER
VARYING
(
32
)
définit une colonne comportant au maximum 32 caractères.
Le synonyme VARCHAR peut être utilisé
NATIONAL CHARACTER et NATIONALCHARACTERVARYING sont des déclinaisons des deux exemples précédents, mais codés sur le jeu UNICODE, ce qui suppose 4 octets par caractère.
Les synonymes NATIONAL CHAR, NCHAR, NATIONAL CHAR VARYING et NATIONAL VARCHAR peuvent être utilisés.
DECIMAL est un réel représentant un nombre en base 10 sans altération de la précision des chiffres situés après la virgule. La précision p peut aller au-delà du maximum prévu pour le traitement des données numériques du processeur.
Exemple 29
DECIMAL
(
60
, 16
)
définit une colonne comportant un réel acceptant jusqu'à 60 chiffres significatifs avec 16 chiffres après la virgule. Aucune erreur d'arrondi ne doit apparaître dans le stockage ni les calculs décimaux.
NUMERIC est un réel représentant un nombre en base 10 sans altération de la précision des chiffres situés après la virgule. La précision p ne peut dépasser le maximum prévu pour le traitement des données numérique du processeur.
Exemple 30
DECIMAL
(
16
, 2
)
définit une colonne comportant un réel acceptant jusqu'à 16 chiffres significatifs avec 2 chiffres après la virgule. Aucune erreur d'arrondi ne doit apparaître dans le stockage ni les calculs décimaux.
FLOAT est un réel représentant un nombre en base 10 stocké en binaire. La précision p peut aller au-delà du maximum prévu pour le traitement des données numériques du processeur.
Exemple 31
FLOAT
(
64
, 16
)
définit une colonne comportant un réel codé en binaire acceptant jusqu'à 64 chiffres significatifs avec 16 chiffres après la virgule. Des erreurs d'arrondi peuvent apparaître dans le stockage ou les calculs décimaux.
REAL est un réel représentant un nombre en base 10 stocké en binaire. La précision p ne peut dépasser le maximum prévu pour le traitement des données numériques du processeur sur un nombre de bits déterminé par le système.
Exemple 32
REAL
(
12
, 4
)
définit une colonne comportant un réel codé en binaire acceptant jusqu'à 12 chiffres significatifs avec 4 chiffres après la virgule. Des erreurs d'arrondi peuvent apparaître dans le stockage ou les calculs décimaux.
DOUBLE PRECISION est un réel représentant un nombre en base 10 stocké en binaire. La précision p ne peut dépasser le maximum prévu pour le traitement des données numérique du processeur sur un nombre de bits déterminé par le système et plus largement que le REAL.
Exemple 33
DOUBLE
PRECISION
(
18
, 6
)
définit une colonne comportant un réel codé en binaire acceptant jusqu'à 18 chiffres significatifs avec 6 chiffres après la virgule. Des erreurs d'arrondi peuvent apparaître dans le stockage ou les calculs décimaux.
SMALLINT est un entier représentant un nombre en base 10 stocké en binaire. La précision est fixe et déterminée par le processeur pour un demi-mot.
Exemple 34
SMALLINT
définit une colonne comportant un entier codé en binaire dont la plage de valeurs est fixée dans l'étendue des capacités du demi-mot du processeur. Les calculs et le stockage sont toujours exacts.
INTEGER est un entier représentant un nombre en base 10 stocké en binaire. La précision est fixe et déterminée par le processeur pour un mot entier.
Exemple 35
INTEGER
définit une colonne comportant un entier codé en binaire dont la plage de valeurs est fixée dans l'étendue des capacités du mot entier du processeur. Les calculs et le stockage sont toujours exacts.
BIT définit une chaîne de bits dont la longueur est fixe.
Exemple 36
BIT
(
2
)
définit une colonne comportant deux bits pouvant avoir les valeurs 00 01 10 ou 11.
BIT VARYING définit une chaîne de bits dont la longueur est variable.
Exemple 37
BIT
(
8
)
définit une colonne comportant au maximum 8 bits pouvant prendre la plage de valeurs allant de 0 à 11111111.
TIMESTAMP combine date et heure avec une précision du millième de seconde. On peut préciser le fuseau horaire avec l'option TIME ZONE. La norme SQL 2 précise que l'étendue de ce type de données doit aller du premier janvier de l'an 1 à zéro heure jusqu'au 31 décembre de l'an 9999 à 23h59m59s999.
Exemple 38
TIMESTAMP
L'option TIME ZONE permet de définir le décalage horaire par rapport à l'heure universelle (UTC) :
Exemple 39
TIMESTAMP
WITH
TIME
ZONE
Par exemple en été en France, où le décalage horaire est de +2 heures par rapport au temps universel, nous pourrions stocker des données sous la forme :
Exemple 40
CAST
(
'1999-11-20 16:28:33-02:00'
AS
TIMESTAMP
WITH
TIME
ZONE)
DATE permet de stoker des dates dans l'étendue premier janvier de l'an 1 jusqu'au 31 décembre de l'an 9999.
Exemple 41
DATE
TIME permet de stocker des heures dans l'étendue de 00:00:00.000 h à 23:59:59.999 h. Comme dans le cas du TIMESTAMP, l'option TIME ZONE permet de définir le décalage horaire par rapport à l'heure universelle (UTC) :
Exemple 42
TIME
WITH
TIME
ZONE
NOTA : pour les types DATE, TIME et TIMESTAMP, le format de saisie est calé sur la norme ISO qui précise que les données temporelles doivent être écrites de la manière suivante : AAAA-MM-JJ et les heures : HH:MM:ss.xxx
ATTENTION : d'après la norme, on peut préciser le nombre de chiffres significatifs après la seconde des types TIME et TIMESTAMP. Ainsi, la déclaration d'un TIMESTAMP(6) permettrait de stocker des informations horaires avec une précision du milliardième de seconde. Compte tenu de la difficulté d'implémentation, de stockage et de calculs de telles données, ce dispositif est rarement implémenté sur les SGBDR des différents éditeurs.
INTERVAL est un type de données permettant de stocker des durées. Le stockage peut se faire sur une unité de temps ou sur une étendue d'unité continuelle de temps à l'aide des mots clefs YEAR, MONTH, DAY, HOUR, MINUTE, SECOND.
La syntaxe de déclaration d'un tel type est la suivante :
Sélectionnez
|
Sélectionnez
|
Avec les règles suivantes : |
Exemple 43
INTERVAL
MINUTE
INTERVAL
YEAR
TO
DAY
INTERVAL
HOUR
TO
SECOND
Si vous désirez mesurer des durées en heures, vous pouvez par exemple stocker 178 heures 23 minutes et 16 secondes sous la forme suivante :
Exemple 44
CAST
(
'178:23:16'
AS
INTERVAL
HOUR
TO
SECOND
)
NOTA : Ce type INTERVAL est malheureusement rarement implémenté. La plupart du temps les éditeurs recommandent d'utiliser un FLOAT pour stocker des durées en fraction de jour.
REMARQUE : on peut être étonné de l'absence de type « booléen » dans la norme. Il est facile de pallier en utilisant un type BIT(1). En l'absence du type BIT, on peut utiliser un SMALLINT associé à une règle de validation ou bien un littéral de type CHAR(1) avec une plage de valeurs.
ATTENTION : lorsqu'une ligne est ajoutée à une table, les colonnes non renseignées possèdent le marqueur NULL.
5-1-2. Typage rapide avec des préfixes▲
Comment préciser le type cible d'une chaîne de caractère ? Là encore la norme vient à notre rescousse. En principe une chaîne de caractères est par défaut du type CHAR ou VARCHAR. Pour la convertir en NATIONAL (CHAR ou VARCHAR) il suffit de la préfixer avec la lettre d'attribut N. De même pour une chaîne représentant une valeur binaire, il faut utiliser la lettre B et pour une chaîne de valeur hexadécimale la lettre X. Il n'y a pas de lettres préfixes pour les autres types. Ainsi pour les chaînes de caractères CHAR / VARCHAR il suffit d'utiliser l'apostrophe comme délimiteur de la chaîne en dédoublant toute apostrophe se trouvant au sein de la chaîne. Enfin pour les données temporelles on peut les préfixer du nom de type.
Exemple 45
'toto' |
chaîne CHAR ou VARCHAR |
N'toto' |
chaîne NATIONAL CHAR ou NATIONAL VARCHAR |
X'AF16' |
chaîne hexadécimale |
B'010011' |
chaîne binaire |
DATE '2002-11-18' |
date |
TIME '11:16' |
heure |
TIMESTAMP '2002-11-18 11:16:22 + 01:00' |
Combiné date/heure avec décalage de fuseau horaire |
INTERVAL '11:16' HOUR TO MINUTE |
Intervalle de temps borné par heures et minutes |
5-2. Les nouveaux types SQL 3▲
La norme SQL 3 (1999) a rajouté 3 types fondamentaux : booléen, CLOB et BLOB.
BOOLEAN est un type de données valant vrai ou faux (ou possédant le marqueur NULL si non renseigné).
Exemple 46
BOOLEAN
NOTA : du fait de la présence du marqueur NULL, le type booléen obéit à une logique ternaire.
CHARACTER LARGE OBJECT [(n [m])] est un type litteral permettant de stocker des chaînes de caractères de grande dimension dans un jeu à deux octets par caractères (ASCII). Le paramètre n permet de préciser la longeur et le paramètre m la mesure de cette longueur parmi les lettres K, M ou G.
Exemple 47
CHARACTER
LARGE OBJECT (
64
K)
Est un type littéral acceptant 64 kilos binaires de caractères, soit 64 * 1024 = 65 536 caractères (donc 131 072 octets).
Le synonyme CLOB peut être utilisé.
NATIONAL CHARACTER LARGE OBJECT [(n [m])] est une déclinaison de CHARACTER LARGE OBJECT opérant sur un jeu à quatre octets par caractères (UNICODE).
Le synonyme NCLOB peut être utilisé.
BINARY LARGE OBJECT [(n [m])] définit une chaîne de bits de grande dimension dont la longueur est fixe. Le paramètre n permet de préciser la longeur et le paramètre m la mesure de cette longueur parmi les lettres K, M ou G.
Exemple 48
BINARY
LARGE OBJECT (
2
G)
Est un type chaîne de bits acceptant 2 gigaoctets de données, soit 2 097 152 octets.
Le synonyme BLOB peut être utilisé.
La norme SQL 3 a de plus défini les types structurés ARRAY, ROW, REF ainsi que des types utilisateurs appelés UDT.
Syntaxe :
Sélectionnez
|
Sélectionnez
|
Sélectionnez
|
Exemple 49
MA_TABLEAU INTEGER
ARRAY
[12, 31]
MON_ADRESSE ROW
(
ADRESSE1 VARCHAR
(
32
)
, ADRESSE2 VARCHAR
(
32
)
, ADRESSE3 VARCHAR
(
32
)
,
CODE_POSTAL CHAR
(
5
)
, VILLE CHAR
(
32
))
MON_CODE_POSTAL REF
(
UDT_CP)
SCOPE TR_CODES_POSTAUX REFERENCES
ARE CHECKED ON
DELETE
SET
NULL
Ces trois exemples montrent :
- un tableau d'entiers à deux dimensions doté de 12 lignes et 31 colonnes ;
- une ligne dotée de 5 éléments permettant de stocker des adresses ;
- une donnée référentielle basée sur un type utilisateur permettant de restreindre les valeurs aux données situées dans une autre table.
Bien entendu ces types peuvent être combinés :
Exemple 50
MON_ADRESSE ROW
(
VARCHAR
(
32
)
ARRAY
[3]
,
CODE_POSTAL REF
(
UDT_CP)
SCOPE TR_CODES_POSTAUX REFERENCES
ARE CHECKED ON
DELETE
SET
NULL
,
VILLE CHAR
(
32
))
REMARQUE : il n'entre pas dans ce papier d'expliquer les UDT dont l'intérêt et la complexité mérite un papier à part entière. Néanmoins les UDT permettent de définir de nouveaux types de données, par exemple pour stocker des coordonnées planaires ou spatiales (polaire, cartésiennes…), des adresses IP, etc.
5-3. Types communs présents dans certains SGBDR des différents éditeurs▲
On trouve couramment les types suivants dans certains SGBDR :
Sélectionnez
|
un format raccourcit pour des dates dans une plage de valeurs restreinte (à éviter) |
Sélectionnez
|
un format spécifique aux valeurs monétaires (à éviter) |
Sélectionnez
|
un entier avec une plage de valeurs très restreinte (par exemple 0 à 255) |
Sélectionnez
|
un entier avec une plage de valeurs très étendue |
Sélectionnez
|
autres noms des CLOB et NCLOB |
Sélectionnez
|
un BLOB spécialisé pour stocker des images |
Sélectionnez
|
autre nom d'un BLOB |
Sélectionnez
|
fichier externe de BLOB (Oracle) |
Sélectionnez
|
données « brutes » |
Sélectionnez
|
des identifiants spécifiques autogénérés |
Sélectionnez
|
des valeurs dans un ensemble prédéfini |
Ces types ne sont pas normatifs, il convient donc de les éviter pour des raisons de portabilité.
5-4. Définir des domaines et les utiliser▲
Un domaine au sens de la norme SQL est la définition d'un type associé à un certain nombre de règles de validité.
Imaginons que nous voulons modéliser le nombre de pages d'un livre. Il est à priori absurde d'accepter un nombre de pages négatif ou nul. Dans ce cas, il faudrait créer un nouveau type dont la plage des valeurs serait restreinte. D'où l'idée de domaine qui rassemble à la fois le type et l'étendue des valeurs possibles, c'est-à-dire le domaine des possibilités d'exploitation.
La définition d'un domaine s'opère avec la syntaxe suivante :
Sélectionnez
|
Sélectionnez
|
NOTA : une règle de validation doit utiliser le mot clef VALUE pour faire référence à la donnée.
Exemple 51
CREATE
DOMAIN NOMBRE_DE_PAGE
AS
INTEGER
CONSTRAINT
CTR_SUP_ZERO CHECK
(
VALUE
>
0
)
La clause DEFAULT d'un ordre de création de domaine peut contenir une valeur explicite, ou bien l'une des valeurs retournées par les fonctions suivantes :
Sélectionnez
|
date courante |
Sélectionnez
|
heure courante |
Sélectionnez
|
date et heure courante |
Sélectionnez
|
heure courante sans fuseau |
Sélectionnez
|
heure et date courante sans fuseau |
Sélectionnez
|
utilisateur par défaut |
Sélectionnez
|
utilisateur courant |
Sélectionnez
|
utilisateur de la session |
Sélectionnez
|
utilisateur système |
Sélectionnez
|
non renseigné |
Exemple 52
CREATE
DOMAIN OUI_NON
AS
NCHAR
(
3
)
DEFAULT
'NON'
CONSTRAINT
CTR_LISTE_VALEUR CHECK
(
UPPER
(
VALUE
)
IN
(
'OUI'
, 'NON'
))
COLLATE
UNICODE
Cet exemple crée un domaine de type 3 caractères UNICODE sur la séquence de collation UNICODE (4 octets par caractères, ordre binaire) avec la valeur par défaut 'NON' et accepte toutes les combinaisons de valeurs suivantes :
'oui', Oui', 'OUi', 'OUI', 'oUI', 'OuI', 'oUi', 'ouI', 'non', 'Non', 'nOn', 'noN', 'NOn', 'nON', 'NoN', 'NON'
Exemple 53
CREATE
DOMAIN IMMATRICULATION
AS
CHAR
(
10
)
CONSTRAINT
CTR_CARACTERE_1 CHECK
(
SUBSTRING
(
VALUE
, 1
, 1
)
BETWEEN
'0'
AND
'9'
)
CONSTRAINT
CTR_CARACTERE_2 CHECK
(
SUBSTRING
(
VALUE
, 2
, 1
)
BETWEEN
'0'
AND
'9'
)
CONSTRAINT
CTR_CARACTERE_3 CHECK
(
SUBSTRING
(
VALUE
, 3
, 1
)
BETWEEN
'0'
AND
'9'
)
CONSTRAINT
CTR_CARACTERE_4 CHECK
(
SUBSTRING
(
VALUE
, 4
, 1
)
=
' '
)
CONSTRAINT
CTR_CARACTERE_5 CHECK
(
SUBSTRING
(
VALUE
, 5
, 1
)
BETWEEN
'A'
AND
'Z'
)
CONSTRAINT
CTR_CARACTERE_5_BIS CHECK
(
SUBSTRING
(
VALUE
, 5
, 1
)
NOT
IN
(
'I'
, 'O'
))
CONSTRAINT
CTR_CARACTERE_6 CHECK
(
SUBSTRING
(
VALUE
, 6
, 1
)
BETWEEN
'A'
AND
'Z'
)
CONSTRAINT
CTR_CARACTERE_6_BIS CHECK
(
SUBSTRING
(
VALUE
, 6
, 1
)
NOT
IN
(
'I'
, 'O'
))
CONSTRAINT
CTR_CARACTERE_7 CHECK
(
SUBSTRING
(
VALUE
, 7
, 1
)
BETWEEN
'A'
AND
'Z'
)
CONSTRAINT
CTR_CARACTERE_7_BIS CHECK
(
SUBSTRING
(
VALUE
, 7
, 1
)
NOT
IN
(
'I'
, 'O'
))
CONSTRAINT
CTR_CARACTERE_8 CHECK
(
SUBSTRING
(
VALUE
, 8
, 1
)
=
' '
)
CONSTRAINT
CTR_CARACTERE_9 CHECK
((
SUBSTRING
(
VALUE
, 9
, 2
)
BETWEEN
'01'
AND
'95'
OR
SUBSTRING
(
VALUE
, 9
, 2
)
IN
(
'2A'
, '2B'
))
AND
NOT
(
SUBSTRING
(
VALUE
, 9
, 2
)
=
'20'
))
Cet exemple permet de modéliser des immatriculations au format : « NNN AAA MM » ou NNN sont des chiffres de 0 à 9, AAA des lettres majuscules de 'A' à 'Z' excepté 'I' et 'O', et un code minéralogique correspondant au numéro des départements de 01 à 95 excepté 20, mais acceptant 2A et 2B pour la Corse !
Bien entendu la norme SQL 2 prévoit la modification d'un domaine en permettant de rajouter ou retirer une clause défaut ou une contrainte :
ALTER
DOMAIN nom_domaine
{ SET
DEFAULT
valeur_défaut
|
DROP
DEFAULT
|
ADD
contrainte_de_domaine
|
DROP
CONSTRAINT
nom_contrainte }
Exemple 54
ALTER
DOMAIN IMMATRICULATION
DROP
CONSTRAINT
CTR_CARACTERE_1
ALTER
DOMAIN IMMATRICULATION
DROP
CONSTRAINT
CTR_CARACTERE_2
ALTER
DOMAIN IMMATRICULATION
DROP
CONSTRAINT
CTR_CARACTERE_3
ALTER
DOMAIN
ADD
CONSTRAINT
CTR_CARACTERE_1_A_3 CHECK
(
CAST
(
SUBSTRING
(
VALUE
, 1
, 3
)
AS
INTEGER
)
BETWEEN
1
AND
999
)
NOTA : il n'est pas possible de changer le type de données de la définition d'un domaine.
La suppression d'un domaine s'effectue avec un ordre SQL DROP :
DROP
DOMAIN nom_domaine [ CASCADE | RESTRICT ]
Lorsque l'on précise CASCADE, le domaine pourra être supprimé sans que les colonnes afférentes à ce domaine en soit affectées. Dans ce cas, le type du domaine comme les contraintes y afférent sont transférés à toutes les colonnes utilisant ce domaine. Si la clause RESTRICT est utilisée, alors une erreur sera levée si des colonnes de table dans la base utilisent le domaine à supprimer. Sinon, la suppression sera effective.
REMARQUE : certains SGBDR n'utilisent pas des domaines, mais proposent des mécanismes similaires.
En particulier c'est le cas de MS SQL Server qui utilise une combinaison de règles et de type utilisateur.
Exemple 55
CREATE
RULE RLE_POURCENT
AS
@VALUE
BETWEEN
0
.0
AND
100
.0
sp_addtype TYP_POURCENT, 'FLOAT'
, 'NOT NULL'
sp_bindrule 'RLE_POURCENT'
, 'TYP_POURCENT'
Création de l'équivalent d'un domaine dans MS SQL Server pour représenter un pourcentage.
NOTA : un domaine est bien entendu utilisable à la place d'un type SQL pour définir une colonne de table.