Les types numériques sont constitués d'entiers de deux, quatre ou huit octets, de nombres à virgule flottante de quatre ou huit octets et de décimaux dont la précision peut être indiquée. Le Tableau 8.2 précise les types disponibles.
Tableau 8.2. Types numériques
Nom | Taille de stockage | Description | Étendue |
---|---|---|---|
smallint | 2 octets | entier de faible étendue | de -32768 à +32767 |
integer | 4 octets | entier habituel | de -2147483648 à +2147483647 |
bigint | 8 octets | grand entier | de -9223372036854775808 à +9223372036854775807 |
decimal | variable | précision indiquée par l'utilisateur, valeur exacte | jusqu'à 131072 chiffres avant le point décimal ; jusqu'à 16383 après le point décimal |
numeric | variable | précision indiquée par l'utilisateur, valeur exacte | jusqu'à 131072 chiffres avant le point décimal ; jusqu'à 16383 après le point décimal |
real | 4 octets | précision variable, valeur inexacte | précision de 6 décimales |
double precision | 8 octets | précision variable, valeur inexacte | précision de 15 décimales |
smallserial | 2 bytes | Entier sur 2 octets à incrémentation automatique | 1 to 32767 |
serial | 4 octets | entier à incrémentation automatique | de 1 à 2147483647 |
bigserial | 8 octets | entier de grande taille à incrémentation automatique | de 1 à 9223372036854775807 |
La syntaxe des constantes pour les types numériques est décrite dans la Section 4.1.2. Les types numériques ont un ensemble complet d'opérateurs arithmétiques et de fonctions. On peut se référer au Chapitre 9 pour plus d'informations. Les sections suivantes décrivent ces types en détail.
Les types smallint
, integer
et
bigint
stockent des nombres entiers, c'est-à-dire
sans décimale, de différentes étendues.
Toute tentative d'y stocker une valeur en dehors de l'échelle
produit une erreur.
Le type integer
est le plus courant. Il offre un
bon compromis entre capacité, espace utilisé et performance.
Le type smallint
n'est utilisé que si l'économie
d'espace disque est le premier critère de choix.
Le type bigint
est conçu pour n'être utilisé que si
l'échelle de valeurs du type integer
n'est pas
suffisante.
SQL ne définit que les types de données
integer
(ou int
),
smallint
et bigint
. Les noms
de types int2
, int4
, et
int8
sont des extensions, partagées par
d'autres systèmes de bases de données SQL.
Le type numeric
peut stocker des nombres contenant un très
grand nombre de chiffres. Il est spécialement recommandé pour stocker les
montants financiers et autres quantités pour lesquels l'exactitude est
indispensable. Les calculs avec des valeurs numeric
renvoient
des résultats exacts quand c'est possible (addition, soustraction,
multiplication).
Néanmoins, les calculs sur les valeurs numeric
sont très
lents comparés aux types entiers ou aux types à virgule flottante
décrits dans la section suivante.
Dans ce qui suit, on utilise les termes suivants. La
précision d'un numeric
est le nombre
total de chiffres significatifs dans le nombre complet, c'est-à-dire le
nombre de chiffres de part et d'autre du séparateur.
L'échelle d'un numeric
est le nombre
de chiffres décimaux de la partie fractionnaire, à droite du séparateur de
décimales. Donc, le nombre 23.5141 a une précision de 6 et une échelle de
4. On peut considérer que les entiers ont une échelle de 0.
La précision maximale et l'échelle maximale d'une colonne numeric
peuvent être toutes deux réglées.
Pour déclarer une colonne de type numérique, il faut utiliser la
syntaxe :
NUMERIC(précision
,échelle
)
La précision doit être strictement positive, l'échelle positive ou NULL. Alternativement :
NUMERIC(précision
)
indique une échelle de 0.
NUMERIC
sans précision ni échelle crée une colonne dans laquelle on
peut stocker des valeurs de n'importe quelle précision ou
échelle, dans la limite de la précision implantée. Une colonne de ce type
n'impose aucune précision à la valeur entrée,
alors que les colonnes numeric
ayant une échelle
forcent les valeurs entrées à cette échelle. (Le standard
SQL demande une précision par défaut de 0,
c'est-à-dire de forcer la transformation en entier. Les auteurs
trouvent cela inutile. Dans un souci de portabilité,
il est préférable de toujours indiquer explicitement la précision et
l'échelle.)
La précision maximale autorisée, si elle est explicitement spécifiée dans
la déclaration du type, est de 1000. NUMERIC
sans précision
est sujet aux limites décrites dans Tableau 8.2.
Si l'échelle d'une valeur à stocker est supérieure à celle de la colonne, le système arrondit la valeur au nombre de décimales indiqué pour la colonne. Si le nombre de chiffres à gauche du point décimal est supérieur à la différence entre la précision déclarée et l'échelle déclarée, une erreur est levée.
Les valeurs numériques sont stockées physiquement sans zéro avant ou
après. Du coup, la précision déclarée et l'échelle de la colonne sont
des valeurs maximales, pas des allocations fixes (en ce sens, le type
numérique est plus proche de varchar(
que
de n
)char(
). Le besoin pour le
stockage réel est de deux octets pour chaque groupe de quatre chiffres
décimaux, plus trois à huit octets d'en-tête.
n
)
En plus des valeurs numériques ordinaires, le type numeric
autorise la valeur spéciale NaN
qui signifie
« not-a-number » (NdT : pas un nombre). Toute opération
sur NaN
retourne NaN
. Pour écrire cette
valeur comme une constante dans une requête SQL, elle doit être placée
entre guillemets. Par exemple,
UPDATE table SET x = 'NaN'
. En saisie, la chaîne
NaN
est reconnue, quelle que soit
la casse utilisée.
Dans la plupart des implémentations du concept « not-a-number »,
NaN
est considéré différent de toute valeur numérique
(ceci incluant NaN
). Pour autoriser le tri des valeurs
de type numeric
et les utiliser dans des index basés sur le
tri, PostgreSQL traite les valeurs
NaN
comme identiques entre elles, mais toutes supérieures
aux valeurs non NaN
.
Les types decimal
et numeric
sont
équivalents. Les deux types sont dans le standard
SQL.
Lors de l'arrondissement de valeurs, le type numeric
arrondit en
s'éloignant de zéro, alors que (sur la plupart des machines) les types
real
et double precision
arrondissent vers le
nombre le plus proche. Par exemple :
SELECT x, round(x::numeric) AS num_round, round(x::double precision) AS dbl_round FROM generate_series(-3.5, 3.5, 1) as x; x | num_round | dbl_round ------+-----------+----------- -3.5 | -4 | -4 -2.5 | -3 | -2 -1.5 | -2 | -2 -0.5 | -1 | -0 0.5 | 1 | 0 1.5 | 2 | 2 2.5 | 3 | 2 3.5 | 4 | 4 (8 rows)
Les types de données real
et double
precision
sont des types numériques inexacts de précision
variable. En pratique, ils sont généralement conformes à la norme
IEEE 754 pour l'arithmétique binaire à
virgule flottante (respectivement simple et double précision),
dans la mesure où les processeurs, le système d'exploitation et
le compilateur les supportent.
Inexact signifie que certaines valeurs ne peuvent être converties exactement dans le format interne. Elles sont, de ce fait, stockées sous une forme approchée. Ainsi, stocker puis réafficher ces valeurs peut faire apparaître de légers écarts. Prendre en compte ces erreurs et la façon dont elles se propagent au cours des calculs est le sujet d'une branche entière des mathématiques et de l'informatique, qui n'est pas le sujet de ce document, à l'exception des points suivants :
pour un stockage et des calculs exacts, comme
pour les valeurs monétaires, le type numeric
doit être
privilégié ;
pour des calculs compliqués avec ces types pour quoi que ce soit d'important, et particulièrement pour le comportement aux limites (infini, zéro), l'implantation spécifique à la plate-forme doit être étudiée avec soin ;
tester l'égalité de deux valeurs à virgule flottante peut ne pas donner le résultat attendu.
Sur la plupart des plates-formes, le type real
a une
étendue d'au moins 1E-37 à 1E37 avec une précision d'au moins
six chiffres décimaux. Le type double precision
a
généralement une étendue de 1E-307 à 1E+308 avec une précision
d'au moins quinze chiffres. Les valeurs trop grandes ou trop petites
produisent une erreur. Un arrondi peut avoir lieu si la précision
d'un nombre en entrée est trop grande. Les nombres trop proches
de zéro qui ne peuvent être représentés autrement que par zéro
produisent une erreur (underflow).
Le paramètre extra_float_digits contrôle le nombre
de chiffres significatifs supplémentaires à inclure quand une valeur à
virgule flottante est convertie en texte. Avec la valeur par défaut de
0
, la sortie est la même sur chaque plate-forme supportée
par PostgreSQL. L'augmenter va produire une sortie qui représentera de
façon plus précise la valeur stockée, mais cela pourrait la rendre non
portable.
Le paramètre extra_float_digits contrôle le nombre
de chiffres significatifs inclus lorsqu'une valeur à virgule flottante
est convertie en texte. Avec la valeur par défaut de
0
, la sortie est la même sur chaque plate-forme
supportée par PostgreSQL. L'augmenter va produire une sortie représentant
plus précisément la valeur stockée, mais il est possible que la sortie
soit différente suivant les plates-formes.
En plus des valeurs numériques ordinaires, les types à virgule flottante ont plusieurs valeurs spéciales :
Infinity
-Infinity
NaN
Elles représentent les valeurs spéciales de l'IEEE 754,
respectivement « infinity » (NdT : infini),
« negative infinity » (NdT : infini négatif) et
« not-a-number » (NdT : pas un nombre) (sur une machine
dont l'arithmétique à virgule flottante ne suit pas l'IEEE 754, ces
valeurs ne fonctionnent probablement pas comme espéré). Lorsqu'elles
sont saisies en tant que constantes dans une commande SQL, ces valeurs
doivent être placées entre guillemets. Par exemple, UPDATE
table SET x = '-Infinity'
. En entrée, ces valeurs sont reconnues,
quelle que soit la casse utilisée.
IEEE754 spécifie que NaN
ne devrait pas être considéré
égale à toute autre valeur en virgule flottante (ceci incluant
NaN
). Pour permettre le tri des valeurs en virgule
flottante et leur utilisation dans des index basés sur des arbres,
PostgreSQL traite les valeurs
NaN
comme identiques entre elles, mais supérieures
à toute valeur différente de NaN
.
PostgreSQL autorise aussi la notation
float
du standard SQL, ainsi que
float(
pour indiquer
des types numériques inexacts. p
)p
indique la précision minimale acceptable en chiffres binaires.
PostgreSQL accepte de
float(1)
à float(24)
, qu'il transforme en
type real
, et de
float(25)
à float(53)
, qu'il transforme en
type double precision
. Toute valeur de
p
hors de la zone des valeurs possibles
produit une erreur. float
sans précision est compris
comme double precision
.
L'affirmation que les real
et les
double precision
ont exactement 24 et 53 bits
dans la mantisse est correcte pour les implémentations des
nombres à virgule flottante respectant le standard IEEE.
Sur les plates-formes non-IEEE, c'est peut-être un peu sous-estimé,
mais, pour plus de simplicité, la gamme de valeurs pour
p
est utilisée sur toutes les
plates-formes.
Cette section décrit une façon spécifique à PostgreSQL de créer une colonne autoincrémentée. Une autre façon revient à utiliser les colonnes d'identité, décrite sur CREATE TABLE.
Les types de données smallserial
, serial
et
bigserial
ne sont pas de vrais types, mais plutôt un
raccourci de notation pour créer des colonnes d'identifiants uniques
(similaires à la propriété AUTO_INCREMENT
utilisée par
d'autres SGBD). Dans la version actuelle, indiquer :
CREATE TABLEnom_de_table
(nom_de_colonne
SERIAL );
est équivalent à écrire :
CREATE SEQUENCEnom_de_table
_nom_de_colonne
_seq AS integer; CREATE TABLEnom_de_table
(nom_de_colonne
integer NOT NULL DEFAULT nextval('nom_de_table
_nom_de_colonne
_seq') NOT NULL ); ALTER SEQUENCEnom_de_table
_nom_de_colonne
_seq OWNED BYnom_de_table
.nom_de_colonne
;
Ainsi a été créée une colonne d'entiers dont la valeur par défaut
est assignée par un générateur de
séquence. Une contrainte NOT NULL
est ajoutée pour
s'assurer qu'une valeur NULL ne puisse pas être
insérée. (Dans la plupart des cas, une
contrainte UNIQUE
ou PRIMARY KEY
peut être ajoutée pour
interdire que des doublons soient créés par accident, mais ce
n'est pas automatique.) Enfin, la séquence est marquée « owned by »
(possédée par) la colonne pour qu'elle soit supprimée si la colonne ou
la table est supprimée.
Comme smallserial
, serial
et
bigserial
sont implémentés en utilisant des séquences,
il peut y avoir des trous dans la séquence de valeurs qui apparait dans
la colonne, même si aucune ligne n'est jamais supprimée. Une valeur
allouée à partir de la séquence est toujours utilisée même si la ligne
contenant cette valeur n'est pas insérée avec succès dans la colonne de
la table. Cela peut survenir si la transaction d'insertion est annulée.
Voir nextval()
dans Section 9.16
pour plus de détails.
Pour insérer la valeur suivante de la séquence dans la colonne
serial
, il faut préciser que la valeur par
défaut de la colonne doit être utilisée. Cela peut se faire de deux façons : soit en
excluant cette colonne de la liste des colonnes de la commande
INSERT
, soit en utilisant le mot-clé
DEFAULT
.
Les types serial
et serial4
sont
identiques : ils créent tous les deux des colonnes
integer
. Les types bigserial
et
serial8
fonctionnent de la même façon, mais créent des
colonnes bigint
. bigserial
doit
être utilisé si plus de 231
identifiants sont prévus sur la durée de vie de la table.
Les noms de type smallserial
et
serial2
fonctionnent de la même façon, sauf qu'ils créent
une colonne de type smallint
.
La séquence créée pour une colonne serial
est automatiquement
supprimée quand la colonne correspondante est supprimée. La séquence peut
être détruite sans supprimer la colonne, mais
la valeur par défaut de la colonne est alors également supprimée.