3. Types de données

SQL reconnaît quatre types de données principaux, eux-mêmes subdivisés en sous-types. Ces quatre types sont les suivants :
  • Les nombres : subdvisés en nombres entiers ou décimaux, eux-mêmes de type flottant ou exact.
  • Les chaînes de caractères. Les chaînes de caractères doivent toujours être associées à un type d'encodage, qui règle, entre autres, le nombre d'octets utilisé pour coder chaque caractère. Un type caractère peut être de taille fixe ou variable. En général, les serveurs de base de données imposent une limite à la taille d'une chaîne de caractères, de l'ordre de quelques milliers. Cette limite peut être exprimée en octets ou en nombre de caractères. Si l'on souhaite stocker des chaînes de très grande taille, on utilisera un type binaire.
  • Le type date, plutôt appelé type temporel. Il existe plusieurs types temporels, suivant que l'on souhaite enregistrer une date précise à l'heure près, ou au jour près (entre autres).
  • Le type binaire. Ce type est utilisé pour stocker des informations purement binaires (les images par exemple), ou de très grande taille. Ce type est souvent appelé blob (acronyme pour binary large object ) ou parfois clob (acronyme pour character large object ).

3.1. Les types numériques

Les types numériques se divisent en deux parties : les types exacts et les types approximatifs. Les types exacts recouvrent les entiers et les nombres à virgule fixe (qui formellement sont aussi des entiers), et les types approximatifs sont le float et le double des langages de programmation classiques. La table suivante regroupe les types numériques entiers.

Tableau 5. Types numériques entiers

Type SQL Codage
tinyint 8 bits
smallint 16 bits
integer ou int 32 bits
bigint 64 bits

Le type numeric permet de fixer le nombre de digits des nombres que l'on veut stocker, et le nombre de chiffres après la virgule de ces chiffres. Ainsi numeric(p, s) ( p comme précision et s comme scale) définit un nombre à p digits et s chiffres après la virgule. La valeur de s est facultative, elle vaut 0 par défaut. Enfin, les types approchés sont float et double, de façon classique.

3.2. Les types caractère

Le codage des caractères est un problème en soi, particulièrement complexe du fait de la grande profusion du nombre de caractères utilisés dans le monde, et de leur classement. Une réponse partielle aux limitations du code ASCII (sur 8 bits) a été apportée par l'introduction de l'Unicode. L'Unicode propose de coder les caractères sur un nombre variable d'octets, pouvant aller d'un seul (afin de conserver la compatibilité avec l'ASCII), jusqu'à 4, afin de supporter toutes les combinaisons de diacritiques existantes. Tous les serveurs de bases de données récents supportent l'Unicode (au moins l'UTF-8). La définition de l'encodage des textes se fait ensuite à plusieurs niveaux. Il existe en général un encodage par défaut défini au niveau de la base de données, qui peut être surchargé au niveau de chaque table, puis à nouveau surchargé au niveau de chaque colonne. À tout ceci s'ajoute la méthode de comparaison des chaînes de caractères. Un simple tri alphabétique peut masquer une réelle complexité. Prend-on en compte les différences miniscules / majuscules ? Comment compare-t-on un caractère accentué et le même caractère sans accent, ou avec un accent différent ? Il est possible de fixer des règles dites de collation , qui fixent précisément la façon dont ces chaînes sont comparées. Tous les types présentés ici supportent la définition d'un jeu de caractère, et la collation.

3.2.1. Le type char

Le type char permet de stocker des chaînes de caractères de taille fixe, comprise entre 0 et 255. Si l'on enregistre une chaîne plus courte que la taille indiquée, alors le serveur ajoute des espaces automatiquement à la fin de la chaîne.

3.2.2. Le type varchar

Le type varchar permet de stocker des chaînes de caractères de taille variable, comprise entre 0 et 65535. Aucun ajout d'espace n'est effectué si une chaîne plus courte que la taille indiquée est enregistrée.

3.2.3. Le type text

Le type text permet de stocker des textes de grande taille. Il en existe quatre formes en MySQL : TinyText, Text, MediumText et LongText. La table suivante donne les tailles de texte que l'on peut stocker dans ces différents champs. On remarquera que cette taille est donnée en octets et non en nombre de caractères. Suivant l'encodate utilisé, le nombre de caractères stockés pourra donc varier.

Tableau 6. Taille des types text pour MySQL

Type texte taille
tinytext 2 8 octets
text 2 16 octets
mediumtext 2 24 octets
longtext 2 32 octets

3.3. Les types temporels

La gestion des dates en SQL est reconnue comme étant un des sujets les plus complexes et les plus épineux du langage. Nous allons le prendre de la façon la plus simple possible, en tentant de rendre les choses accessibles. Tout d'abord, il existe trois types différents pour enregistrer des dates : time, date et timestamp.

3.3.1. Type date

Une date est composée de trois éléments :
  • une année, codée sur un entier de quatre digits ;
  • un mois, codé sur un entier de 1 à 12 ;
  • un jour, codé sur un entier de 1 à 31.
En MySQL, le type date permet de coder des dates de '1000-01-01' à '9999-31-12'.

3.3.2. Type time

Le type time est également composé de trois éléments :
  • une heure, codée sur un entier de 0 à 23 ;
  • une minute, codée sur un entier de 0 à 59 ;
  • une seconde, codée sur un entier de 0 à 59.
En MySQL, le type time permet de coder des dates sur une gamme beaucoup plus large, allant de -838:59:59 à 838:59:59. Effectivement ce type est utilisé pour coder à la fois les heures de la journée, mais aussi des intervalles temporels exprimés en heures.

3.3.3. Type datetime et timestamp

Ces deux derniers types sont des compositions d'une date et d'un time. Ils permettent donc de coder une date à la seconde près. En MySQL, il existe une différence sournoise entre ces deux types :
  • le type datetime permet de coder des dates de 1000-01-01 00:00:00 à 9999-12-31 23:59:59 ;
  • le type timestamp permet de coder des dates de 1970-01-01 00:00:01 à 2038-01-19 03:14:07.
On prendra donc garde aux limitations de ces différents types lors de la construction d'une base de données.

3.3.4. Fonctions temporelles

La dernière difficulté que l'on peut rencontrer lorsque l'on manipule des dates provient de la nature même de ces données. On ne manipule une date qu'au travers de sa représentation, sous forme de chaîne de caractères. Si l'on tente d'insérer une date dans une table, en ne donnant que la chaîne de caractères qui la représente, on a toutes les chances de prendre un message d'erreur assez obscur, et en tout cas peu utile (c'est en tout cas le cas sous Oracle et MySQL) ! Passer d'une date à sa représentation sous forme de chaîne est automatique, l'affichage ne posera donc jamais de problème. Le contraire est en revanche problématique. Sous MySQL il faut utiliser les fonctions de conversion suitantes :
  • date() : convertit une chaîne en date, ex : date('1918-11-11')
  • time() : convertit une chaîne en time, ex : time('10:25:45')
  • timestamp() : convertit une chaîne en datetime, ex : timestamp('1918-11-11 10:25:45')
Une commande d'insertion ou de mise à jour de données devra donc utiliser ces fonctions de conversion pour fonctionner. Tous les serveurs de base de données proposent une liste importante de fonctions permettant de manipuler les dates : recherche du nom d'un jour, du dernier jour d'un mois, arithmétique sur les dates, etc... On pourra se référer aux documentations pour la liste exhasutive. Enfin, citons les fonctions temporelles de MySQL qui permettent d'obtenir la date du jour :
  • curdate() : retourne l'instant présent sous forme de date ;
  • curtime() : retourne l'instant présent sous forme de time ;
  • now() : retourne l'instant présent sous forme de datetime.
Toutes ces fonctions peuvent être appelées dans un select, et utilisées comme argument d'un insert ou d'une update.

3.4. Les types binaires

Le type binaire est déclaré avec le mot-clé blob (binary large object). En MySQL, il existe quatre types de blobs, correspondant aux quatre types de textes de grande taille, et de même taille :

Tableau 7. Taille des types blob pour MySQL

Type blob taille
tinyblob 2 8 octets
blob 2 16 octets
mediumblob 2 24 octets
longblob 2 32 octets

À la différence des text, les blob ne peuvent pas être associés à des jeux de caractères, et ne sont comparables que numériquement. Les blob sont utilisés pour stocker des tableaux de bytes , comme des images, ou des volumes de données importants.

3.5. Type auto-incrémental de MySQL

MySQL a depuis ses débuts introduit un type de données qui lui est propre, destiné à pallier l'absence de sequence. Une colonne auto-incrémentale se déclare comme suit.

Exemple 30. Création d'une colonne auto-incrémentale dans MySQL

create  table Marins (
   id  int auto_increment  primary  key, 
   ...
) ;

On ne peut pas insérer de donnée explicitement dans une colonne auto-incrémentale. Au contraire, MySQL entretient automatiquement la valeur de cette colonne, et nous garantit qu'au sein d'une même table deux lignes ne prendront pas la même valeur. Les colonnes auto-incrémentales sont un moyen pratique de créer des clés primaires.

3.6. Type auto-généré de Derby

Derby expose la même fonctionnalité, sur une principe similaire, mais avec une syntaxe différente. Les colonnes auto-générées de Derby ne peuvent être que de trois types :
  • SMALLINT
  • INT
  • BIGINT
Une colonne auto-générée peut être ensuite de type GENERATED ALWAYS, ou GENERATED BY DEFAULT. Dans le premier cas, il n'est pas possible d'insérer une valeur dans cette colonne ; c'est Derby qui se charge de la remplir. Dans le second cas, Derby autorise l'insertion manuelle de valeurs, et en génère une automatiquement si aucune valeur n'est fournie. Il est de plus possible de spécifier la façon dont les valeurs générées sont produites : le pas d'incrémentation, etc...

Exemple 31. Création d'une colonne générée avec Derby

create  table Marins (
   id  int  primary  key generated always 
           as identity (start  with 1000, increment  by 100), 
   ...
) ;

3.7. Séquences d'Oracle

L'approche proposée par Oracle est différente. Plutôt que de générer des valeurs automatiques dans une table, Oracle expose la notion de séquence . Une séquence est un objet particulier d'une base de données, au même titre qu'une table, ou qu'une contrainte. On crée une séquence à l'aide de la commande create sequence seq, dans laquelle seq représente le nom de la séquence que l'on crée. On peut ainsi créer autant de séquences que l'on veut. Une séquence entretient deux valeurs :
  • curval : la valeur courante de cette séquence ;
  • nextval : la valeur suivante de cette séquence ;
Le contrat de ces deux valeurs est le suivant :
  • un appel à curval retourne toujours la valeur retournée par le dernier appel à nextval ;
  • un appel à nextval retourne toujours une valeur nouvelle, en général obtenue en incrémentant la valeur courante.
La garantie que deux appels successifs à nextval ne retournent jamais la même valeur est très forte, et permet d'utiliser les séquences pour générer des clés primaires. Notons toutefois des appels successifs à nextval dans un même select retournent la même valeur. L'intérêt des séquences par rapport aux colonnes auto-incrémentales est qu'il devient possible de créer des clés primaires uniques au sein, non plus d'une table, mais d'un ensemble de tables, voire d'une base de données complète. Cela permet de simplifier les choses lorsque l'on veut réorganiser une base, en fusionnant des tables notamment. Notons enfin qu'Oracle n'expose pas la notion de colonne auto-incrémentale. Il est possible de simuler ce comportement au niveau d'une colonne en créant un trigger .

Exemple 32. Séquences sous Oracle

-- création d'une séquence
 create sequence marins_seq ;

 -- création d'une nouvelle valeur 
 select marins_seq.nextval  from  dual ;

 -- lecture de la valeur courante
 select marins_seq.curval  from  dual ;

Introduction à SQL
Retour au blog Java le soir
Cours & Tutoriaux
Table des matières
Introduction
1. Un peu d'histoire
2. Organisation de la présentation
Un premier exemple
1. Un premier exemple
1.1. Construction d'une première table
1.2. Enregistrer quelques données
1.3. Extraire des données
2. Trier, classer, calculer
2.1. Classer des données
2.2. Trier des données
2.3. Effectuer des calculs
2.4. Mise à jour d'une valeur
3. Sélection sur plusieurs tables
3.1. Ajout du lieu de naissance
3.2. Clés primaires et clés étrangères
Organisation des données
1. Introduction
2. Bases de données, schémas et tables
2.1. Création d'une table
2.2. Création d'une colonne
2.3. Contraintes sur une table
2.4. Nommage des contraintes
2.5. Exemples de création de tables
2.6. Modification d'une table
2.7. Effacement d'une table
2.8. Remarques sur restrict et cascade
3. Types de données
3.1. Les types numériques
3.2. Les types caractère
3.3. Les types temporels
3.4. Les types binaires
3.5. Type auto-incrémental de MySQL
3.6. Type auto-généré de Derby
3.7. Séquences d'Oracle
Manipulation des données
1. Introduction
2. Extraire des données : select
2.1. Extraire des données d'une table unique
2.2. Clause where
2.3. Requêtes imbriquées
2.4. Fonctions d'agrégation, groupage
3. Supprimer des données : delete
3.1. Forme générale du delete
3.2. Effacement en cascade
3.3. Fonctionnement du delete
4. Ajouter des données : insert
4.1. Forme générale de l' insert
4.2. Copie d'une table dans une autre
5. Mettre à jour des données : update
5.1. Forme générale de l' update
5.2. Mise à jour avec une requête imbriquée
Interrogations sur plusieurs tables
1. Introduction
2. Formes normales
2.1. Première forme normale
2.2. Deuxième forme normale
2.3. Troisième forme normale
2.4. Formes normales d'ordres supérieurs
3. Relations entre éléments
3.1. Cardinalité d'une relation
3.2. Relation 1:1
3.3. Relation 1:p
3.4. Relation p:1
3.5. Relation n:p
4. Jointures
4.1. Jointure interne
4.2. Jointure externe
4.3. Auto-jointure
5. Unions
6. Vues
6.1. Création d'une vue
6.2. Exemples de vues
Transactions
1. Introduction
2. Isolation des transactions
2.1. ACIDité d'une transaction
2.2. Définition de l'isolation
3. Gestion d'une transaction
3.1. Mode auto-commit
3.2. Fixer le niveau d'isolation
3.3. Démarrer une transaction
3.4. Terminer une transaction
3.5. Remarques importantes
Index
1. Introduction
2. Manipulation d'index
2.1. Création automatique d'index
2.2. Création manuelle d'index