CREATE TYPE — Définir un nouveau type de données
CREATE TYPEnom
AS (nom_attribut
type_donnée
[ COLLATEcollation
] [, ... ] ) CREATE TYPEnom
AS ENUM ( [ 'label
' [, ... ] ] ) CREATE TYPEname
AS RANGE ( SUBTYPE =sous_type
[ , SUBTYPE_OPCLASS =classe_operateur_sous_type
] [ , COLLATION =collationnement
] [ , CANONICAL =fonction_canonique
] [ , SUBTYPE_DIFF =fonction_diff_sous_type
] [ , MULTIRANGE_TYPE_NAME =nom_type_multirange
] ) CREATE TYPEnom
( INPUT =fonction_entrée
, OUTPUT =fonction_sortie
[ , RECEIVE =fonction_réception
] [ , SEND =fonction_envoi
] [ , TYPMOD_IN =type_modifier_input_function
] [ , TYPMOD_OUT =type_modifier_output_function
] [ , ANALYZE =fonction_analyse
] [ , SUBSCRIPT =fonction_indice
] [ , INTERNALLENGTH = {longueurinterne
| VARIABLE } ] [ , PASSEDBYVALUE ] [ , ALIGNMENT =alignement
] [ , STORAGE =stockage
] [ , LIKE =type_like
] [ , CATEGORY =catégorie
] [ , PREFERRED =préféré
] [ , DEFAULT =défaut
] [ , ELEMENT =élément
] [ , DELIMITER =délimiteur
] [ , COLLATABLE =collatable
] ) CREATE TYPEnom
CREATE TYPE
enregistre un nouveau type de données
utilisable dans la base courante. L'utilisateur qui définit un type
en devient le propriétaire.
Si un nom de schéma est précisé, le type est créé dans ce schéma. Sinon, il est créé dans le schéma courant. Le nom du type doit être distinct du nom de tout type ou domaine existant dans le même schéma. Les tables possèdent des types de données associés. Il est donc nécessaire que le nom du type soit également distinct du nom de toute table existant dans le même schéma.
Il existe cinq formes de CREATE TYPE
, comme indiqué dans
la syntaxe ci-dessus. Elles créent respectivement un type
composite, un type enum, un type
range (intervalle), un type de base ou un
type shell. Les autre premiers sont discutés dans
l'ordre ci-dessous. Un type shell est un simple conteneur de type qui sera
défini ultérieurement. Il est créé en lançant CREATE
TYPE
sans paramètre en dehors de son nom. Les types shell sont
nécessaires comme référence lors de la création de types intervalles et de types
de base, comme indiqué dans ces sections.
La première forme de CREATE TYPE
crée un type composite. Le
type composite est défini par une liste de noms d'attributs et de types de
données. Un collationnement d'attribute peut aussi être spécifié si son
type de données est collationnable. Un type composite est essentiellement
le même que le type ligne (NDT : row
type en anglais) d'une table, mais l'utilisation de
CREATE TYPE
permet d'éviter la création d'une table
réelle quand seule la définition d'un type est voulue. Un type composite
autonome est utile, par exemple, comme type d'argument ou de retour d'une
fonction.
Pour pouvoir créer un type composite, vous devez avoir le droit
USAGE
sur les types de tous les attributs.
La seconde forme de CREATE TYPE
crée un type énuméré
(enum), comme décrit dans Section 8.7. Les types enum
prennent une liste de plusieurs labels entre guillemets, chacun devant
faire moins de NAMEDATALEN
octets (64 octets dans une
installation PostgreSQL standard). (Il est
possible de créer un type énuméré avec zéro label, mais un tel type ne
peut pas être utilisé pour contenir des valeurs avant qu'au moins un label
soit ajouté en utilisant ALTER TYPE
.)
La troisième forme de CREATE TYPE
crée un type intervalle,
comme décrit dans Section 8.17.
Le sous-type
du type intervalle
peut être de tout type qui soit associé avec une classe d'opérateur B-tree
(pour déterminer l'ordre des valeurs pour le type intervalle). Habituellement,
la classe d'opérateur par défaut du sous-type est utilisée pour déterminer
l'ordre. Pour utiliser un opérateur de classe autre que celle par défaut,
indiquez son nom avec classe_operateur_sous_type
. Si le sous-type
est collationnable et que vous voulez utiliser un collationnement autre que
celui par défaut dans l'ordre de l'intervalle, indiquez le collationnement
souhaité avec l'option collationnement
.
La fonction optionnelle canonique
prend un argument du type intervalle défini, et renvoie une valeur du même
type. C'est utilisé pour convertir les valeurs intervalles en leur forme
canonique, lorsque c'est applicable. Voir Section 8.17.8 pour plus d'informations. Créer une fonction
canonique
peut être un peu
compliqué car il doit être défini avant que le type intervalle ne soit défini.
Pour cela, vous devez tout d'abord créer un type shell, qui est un coquille
vide qui n'a aucune propriété en dehors de son nom et propriétaire. Cela
se crée en exécutant la commande CREATE TYPE
, sans paramètre supplémentaire.
Ensuite, la fonction peut être déclarée en utilisant le type shell comme
argument et résultat. Enfin, le type intervalle peut être déclaré en utilisant
le même nom. Ceci remplace automatiquement l'entrée du type shell avec
un type intervalle valide.
nom
La fonction optionnelle diff_sous_type
doit prendre deux valeurs du type sous-type
comme arguments, et renvoie une
valeur de type double precision
représentant la différence
entre les deux valeurs données. Bien que cela soit optionnel, la fournir
autorise une plus grande efficacité des index GiST sur les colonnes du type
intervalle. Voir Section 8.17.8 pour plus
d'informations.
Le paramètre optionnel nom_type_multirange
indique le nom du type multirange correspondant. Si non specifié, ce nom
est choisi automatiquement comme suit. Si le type de type range contient
la sous-chaîne range
, alors le nom du type multirange
est formé par le remplacement de la sous-chaîne avec
multirange
dans le nom du type range. Sinon le nom du
type multirange est formé en ajoutant le suffixe
_multirange
au nom du type range.
La quatrième forme de CREATE TYPE
crée un nouveau type de base
(type scalaire). Pour créer un nouveau type de base, il faut être superutilisateur.
(Cette restriction est imposée parce qu'une définition de type erronée pourrait
embrouiller voire arrêter brutalement le serveur.)
L'ordre des paramètres, dont la plupart sont optionnels, n'a aucune
d'importance. Avant de définir le type, il est nécessaire de définir au moins
deux fonctions (à l'aide de la commande CREATE FUNCTION
).
Les fonctions de support fonction_entrée
et fonction_sortie
sont obligatoires. Les
fonctions fonction_réception
,
fonction_envoi
,
type_modifier_input_function
,
type_modifier_output_function
,
fonction_analyse
et
fonction_indice
sont
optionnelles. Généralement, ces fonctions sont codées en C ou dans un
autre langage de bas niveau.
La fonction_entrée
convertit la
représentation textuelle externe du type en représentation interne
utilisée par les opérateurs et fonctions définis pour le type.
La fonction_sortie
réalise la transformation
inverse. La fonction entrée peut être déclarée avec un
argument de type cstring
ou trois arguments de
types cstring
, oid
, integer
. Le
premier argument est le texte en entrée sous la forme d'une chaîne C, le second
argument est l'OID du type (sauf dans le cas des types tableau où il
s'agit de l'OID du type de l'élément) et le troisième est le typmod
de la colonne destination, s'il est connu (-1 sinon). La fonction entrée
doit renvoyer une valeur du nouveau type de données.
Habituellement, une fonction d'entrée devrait être déclarée comme STRICT
si ce n'est pas le cas, elle sera appelée avec un premier paramètre NULL à
la lecture d'une valeur NULL en entrée. La fonction doit toujours envoyer
NULL dans ce cas, sauf si une erreur est rapportée.
(Ce cas a pour but de supporter les fonctions d'entrée des domaines qui ont
besoin de rejeter les entrées NULL.)
La fonction sortie doit prendre un argument du nouveau type de données, et
retourner le type cstring
. Les fonctions sortie ne sont pas
appelées pour des valeurs NULL.
La fonction_réception
,
optionnelle, convertit la représentation binaire externe du type en
représentation interne.
Si cette fonction n'est pas fournie, le type n'accepte pas
d'entrée binaire. La représentation binaire est choisie de telle sorte
que sa conversion en forme interne soit peu coûteuse, tout en restant
portable. (Par exemple, les types de données
standard entiers utilisent l'ordre réseau des octets comme représentation
binaire externe alors que la représentation interne est dans l'ordre natif
des octets de la machine.) La fonction de réception réalise les
vérifications adéquates pour s'assurer que la valeur est valide. Elle
peut être déclarée avec un argument de type
internal
ou trois arguments de types
internal
, integer
et oid
. Le premier
argument est un pointeur vers un tampon StringInfo
qui contient la chaîne d'octets reçue ; les arguments optionnels sont les
mêmes que pour la fonction entrée de type texte. La fonction de réception
retourne une valeur du type de données.
Habituellement, une fonction de réception devrait être déclarée comme STRICT
si ce n'est pas le cas, elle sera appelée avec un premier paramètre NULL à
la lecture d'une valeur NULL en entrée. La fonction doit toujours envoyer
NULL dans ce cas, sauf si une erreur est rapportée.
(Ce cas a pour but de supporter les fonctions de réception des domaines qui ont
besoin de rejeter les entrées NULL.)
De façon similaire, la
fonction_envoi
, optionnelle,
convertit la représentation interne en représentation
binaire externe. Si cette fonction n'est pas fournie, le type
n'accepte pas de sortie binaire. La fonction d'envoi doit être déclarée
avec un argument du nouveau type de données et retourner le type bytea
.
Les fonctions réception ne sont pas appelées pour des valeurs NULL.
À ce moment-là, vous pouvez vous demander comment les fonctions d'entrée et
de sortie peuvent être déclarées avoir un résultat ou un argument du nouveau
type alors qu'elles sont à créer avant que le nouveau type ne soit créé. La
réponse est que le type sera tout d'abord défini en tant que
type squelette (shell type),
une ébauche de type sans propriété à part un nom et un propriétaire. Ceci se
fait en exécutant la commande CREATE TYPE
sans paramètres supplémentaires. Ensuite, les fonctions d'entrée/sortie C
peuvent être définies en référençant le squelette. Enfin, le
nom
CREATE TYPE
avec une définition complète remplace le
squelette avec une définition complète et valide du type, après quoi le
nouveau type peut être utilisé normalement.
Les fonctions optionnelles
type_modifier_input_function
et type_modifier_output_function
sont nécessaires si le type supporte des modificateurs, c'est-à-dire des
contraintes optionnelles attachées à une déclaration de type comme
char(5)
ou numeric(30,2)
.
PostgreSQL autorise les types définis par
l'utilisateur à prendre une ou plusieurs constantes ou identifiants comme
modifieurs ; néanmoins, cette information doit être capable d'être
englobée dans une seule valeur entière positive pour son stockage dans les
catalogues système.
type_modifier_input_function
se voit fournir le modifieur déclaré de la forme d'un tableau de
cstring
. Il doit vérifier la validité des valeurs et renvoyer une
erreur si elles sont invalides. Dans le cas contraire, il renvoie une valeur
entière positive qui sera stockée dans la colonne « typmod ». Les
modifieurs de type seront rejetés si le type n'a pas de
type_modifier_input_function
.
type_modifier_output_function
convertit la valeur typmod integer en une forme correcte pour l'affichage.
Il doit renvoyer une valeur de type cstring
qui est la chaîne
exacte à ajouter au nom du type ; par exemple la fonction de
numeric
pourrait renvoyer (30,2)
. Il est
permis d'omettre le
type_modifier_output_function
,
auquel cas le format d'affichage par défaut est simplement la valeur typmod
stockée entre parenthèses.
La fonction_analyse
, optionnelle,
calcule des statistiques spécifiques au type de données pour les
colonnes de ce type. Par défaut, ANALYZE
tente de
récupérer des statistiques à l'aide des opérateurs d'« égalité » et
d'« infériorité » du type, s'il existe une classe d'opérateur B-tree
par défaut pour le type. Ce comportement est inadapté aux types non-scalaires ;
il peut être surchargé à l'aide d'une fonction
d'analyse personnalisée. La fonction d'analyse doit être déclarée avec
un seul argument de type internal
et un résultat de type
boolean
. L'API détaillée des fonctions d'analyses est présentée dans
src/include/commands/vacuum.h
.
La fonction optionnelle fonction_indice
autorise l'utilisation
d'indice pour le type de données dans les commandes SQL. Indiquer cette
fonction ne fait pas en sorte que le type soit considéré comme un
« vrai » type tableau ; par exemple, il ne sera pas un
candidat pour le type résultat de constructions ARRAY
[]
. Mais si indicer une valeur du type est une notation
naturelle pour en extraire des données, alors une fonction_indice
peut être écrite pour
définir la signification. La fonction d'indice doit être déclarée comme
prenant un seul argument de type internal
, et renvoyer un
résultat de type internal
, qui est un pointeur vers une
structure de méthodes (fonctions) qui implémentent l'indiçage. L'API
détaillée pour les fonctions d'indice apparaît dans in
src/include/nodes/subscripting.h
. Il pourrait aussi
être utile de lire l'implémentation des tableaux dans
src/backend/utils/adt/arraysubs.c
, ou le code simple
de contrib/hstore/hstore_subs.c
. Des informations
supplémentaires apparaissent dans Types tableau,
ci-dessous.
Alors que les détails de la représentation interne du nouveau type ne sont
connus que des fonctions d'entrées/sorties et des fonctions utilisateurs
d'interaction avec le type, plusieurs propriétés de
la représentation interne doivent être déclarées à
PostgreSQL. La première est
longueurinterne
. Les types de
données basiques peuvent être de longueur fixe (dans ce cas,
longueurinterne
est un entier positif)
ou de longueur variable (indiquée par le positionnement de
longueurinterne
à
VARIABLE
; en interne, cela est représenté en initialisant
typlen
à -1). La représentation interne de tous les types de
longueur variable doit commencer par un entier de quatre octets indiquant la
longueur totale de cette valeur. (Notez que le champ length est souvent
encodé, comme décrit dans Section 65.2 ; il n'est
pas conseillé d'y accéder directement.)
Le drapeau optionnel PASSEDBYVALUE
indique que les
valeurs de ce type de données sont passées par valeur plutôt que par
référence. Les types dont la représentation interne est plus grande que la
taille du type Datum
(quatre octets sur la plupart des
machines, huit sur quelques-unes) ne doivent pas être passés par valeur.
Les types passés par valeur doivent avoir une longueur fixe et leur
représentation interne ne peut pas être plus large que la taille du type
Datum
(4 octets sur certaines machines, 8 octets sur
d'autres).
Le paramètre alignement
spécifie l'alignement de stockage requis pour le type de données. Les
valeurs permises sont des alignements sur 1, 2, 4 ou 8 octets.
Les types de longueurs variables ont un alignement d'au
moins quatre octets car leur premier composant est nécessairement un int4
.
Le paramètre stockage
permet de
choisir une stratégie de stockage pour les types de données de longueur
variable. (Seul plain
est autorisé pour les types de
longueur fixe.) plain
indique des données
stockées en ligne et non compressées.
Dans le cas d'extended
le système essaie tout d'abord de
compresser une valeur longue et déplace la valeur hors de
la ligne de la table principale si elle est toujours trop longue.
external
permet à la valeur d'être déplacée hors de la
table principale mais le système ne tente pas de la compresser.
main
autorise la compression mais ne déplace
la valeur hors de la table principale qu'en dernier recours.
(Ils seront déplacés s'il n'est pas possible de placer la ligne
dans la table principale, mais
sont préférentiellement conservés dans la table principale, contrairement aux éléments
extended
et external
.)
Toutes les valeurs storage
autres que plain
impliquent que les fonctions du type
de données peuvent gérer les valeurs placées en
TOAST, comme décrit dans Section 65.2 et Section 36.13.1. L'aure valeur
spécifique détermine la stratégie de stockage par défaut pour les colonnes
d'un type de données externalisable ; les utilisateurs peuvent
sélectionner les autres stratégies pour les colonnes individuelles en
utilisant ALTER TABLE SET STORAGE
.
Le paramètre type_like
fournit
une méthode alternative pour spécifier les propriétés de représentation de
base d'un type de données : les copier depuis un type existant. Les valeurs
de longueurinterne
,
passedbyvalue
,
alignement
et
stockage
sont copiées du type
indiqué. (C'est possible, mais habituellement non souhaité, d'écraser
certaines de ces valeurs en les spécifiant en même temps que la clause
LIKE
.) Spécifier la représentation de cette façon est
particulièrement pratique quand l'implémentation de bas niveau du nouveau type
emprunte celle d'un type existant d'une façon ou d'une autre.
Les paramètres catégorie
et
préféré
peuvent être utilisés pour
aider à contrôler la conversion implicite appliquée en cas d'ambiguïté.
Chaque type de données appartient à une catégorie identifiée par un seul
caractère ASCII, et chaque type est « préféré » ou pas de sa
catégorie. L'analyseur préfèrera convertir vers des types préférés (mais
seulement à partir d'autres types dans la même catégorie) quand cette règle
peut servir à résoudre des fonctions ou opérateurs surchargés. Pour plus de
détails, voir Chapitre 10. Pour les types qui n'ont pas de
conversion implicite de ou vers d'autres types, on peut se contenter de laisser
ces paramètres aux valeurs par défaut. Par contre, pour un groupe de types
liés entre eux qui ont des conversions implicites, il est souvent pratique
de les marquer tous comme faisant partie d'une même catégorie, et de choisir
un ou deux des types les « plus généraux » comme étant les types
préférés de la catégorie.
Le paramètre catégorie
est
particulièrement utile quand on ajoute un type défini par l'utilisateur à un
type interne, comme un type numérique ou chaîne. Toutefois, c'est aussi tout
à fait possible de créer des catégories de types entièrement nouvelles.
Choisissez un caractère ASCII autre qu'une lettre en majuscule pour donner
un nom à une catégorie de ce genre.
Une valeur par défaut peut être spécifiée dans le cas où l'utilisateur
souhaite que cette valeur soit différente de NULL pour les colonnes de ce type.
La valeur par défaut est précisée à l'aide du mot clé
DEFAULT
. (Une telle valeur par défaut peut être surchargée
par une clause DEFAULT
explicite attachée à une colonne
particulière.)
Pour indiquer qu'un type est un tableau de taille fixe, le type des éléments du
tableau est précisé par le mot clé ELEMENT
. Par exemple, pour
définir un tableau d'entiers de quatre octets (int4
),
ELEMENT = int4
est utilisé. Pour plus de détails,
voir Types tableau ci-dessous.
Pour préciser le délimiteur de valeurs utilisé dans la
représentation externe des tableaux de ce type,
délimiteur
peut être positionné à un
caractère particulier. Le délimiteur par défaut est la virgule
(,
). Le délimiteur est associé avec le type
élément de tableau, pas avec le type tableau.
Si le paramètre booléen optionnel collatable
vaut true, les définitions et
expressions de colonnes du type peuvent embarquer une information de
collationnement via la clause COLLATE
. C'est aux
implémentations des fonctions du type de faire bon usage de cette
information. Cela n'arrive pas automatiquement en marquant le type
collationnable.
À chaque fois qu'un type défini par un utilisateur est créé,
PostgreSQL crée automatiquement un type tableau
associé dont le nom est composé à partir du type de base préfixé d'un tiret
bas et tronqué si nécessaire pour que le nom généré fasse moins de
NAMEDATALEN
octets. (Si le nom généré est en conflit avec
un autre nom, le traitement est répété jusqu'à ce qu'un nom sans conflit
soit trouvé.) Ce type tableau créé implicitement est de longueur variable
et utilise les fonctions d'entrée et sortie array_in
et
array_out
. De plus, ce type est ce que le système
utilise pour les constructions telles que ARRAY[]
sur
le type défini par l'utilisateur. Le type tableau trace tout changement
dans du type de base pour le propriétaire et le schéma. Il est aussi
supprimé quand le type de base l'est.
Pourquoi existe-t-il une option
ELEMENT
si le système fabrique automatiquement le bon type
tableau ?
L'utilité principale d'ELEMENT
est la création d'un type de longueur
fixe représenté en interne par un tableau d'éléments identiques auxquels on souhaite
accéder directement par leurs indices (en plus de toute autre opération
effectuée sur le type dans sa globalité). Par exemple, le type
point
est représenté par deux nombres à virgule flottante,
qui sont accessibles par point[0]
et
point[1]
. Cette
fonctionnalité n'est possible qu'avec les types de longueur fixe dont la
forme interne est strictement une séquence de champs de longueur fixée.
Pour des raisons historiques (c'est-à-dire pour de mauvaises raisons, mais
il est trop tard pour changer) les indices des tableaux de types de longueur
fixe commencent à zéro et non à un comme c'est le cas pour les tableaux de
longueur variable.
Ajouter l'option SUBSCRIPT
permet au type de données
d'utiliser des indices, même si le système ne le gère pas comme un type
tableau. Le comportement tout juste décrit pour les tableaux à longueur
fixe est en fait implémenté par la fonction gestionnaire
SUBSCRIPT
appelée
raw_array_subscript_handler
, qui est utilisée
automatiquement si vous indiquez ELEMENT
pour un type de
longueur fixe sans écrire aussi SUBSCRIPT
.
Lors de l'indication explicite d'une fonction SUBSCRIPT
,
il n'est pas nécessaire d'indiquer ELEMENT
sauf si la
fonction gestionnaire SUBSCRIPT
a besoin de consulter
typelem
pour savoir ce qu'elle renvoie. Faites
attentent qu'indiquer ELEMENT
cause le système à assumer
que le nouveau type contient ou est quelque part physiquement dépendant,
du type élément ; de ce fait, changer par exemple les propriétés du
type élément n'est pas autorisé s'il y a des colonnes du type dépendant.
nom
Le nom (éventuellement qualifié du nom du schéma) du type à créer.
nom_attribut
Le nom d'un attribut (colonne) du type composite.
type_données
Le nom d'un type de données existant utilisé comme colonne du type composite.
collationnement
Le nom d'un collationnement existant à associer avec une colonne d'un type composite ou avec un type intervalle.
label
Une chaîne représentant le label associé à une valeur du type enum.
sous_type
Le nom du type élément dont le type intervalle va représenter des intervalles.
classe_operateur_sous_type
Le nom d'une classe d'opérateur B-tree pour le sous-type.
fonction_canonique
Le nom de la fonction canonique pour le type intervalle.
fonction_diff_sous_type
Le nom de la fonction de différence pour le sous-type.
multirange_type_name
Le nom du type multirange correspondant.
fonction_entrée
Le nom d'une fonction de conversion des données de la forme textuelle externe du type en forme interne.
fonction_sortie
Le nom d'une fonction de conversion des données de la forme interne du type en forme textuelle externe.
fonction_réception
Le nom d'une fonction de conversion des données de la forme binaire externe du type en forme interne.
fonction_envoi
Le nom d'une fonction de conversion des données de la forme interne du type en forme binaire externe.
type_modifier_input_function
Le nom d'une fonction qui convertit un tableau de modifieurs pour le type vers sa forme interne.
type_modifier_output_function
Le nom d'une fonction qui convertit la forme interne des modifieurs du type vers leur forme textuelle externe.
fonction_analyze
Le nom d'une fonction d'analyses statistiques pour le type de données.
fonction_indice
Le nom d'une fonction qui définit ce qu'indicer une valeur de ce type de données signifie.
longueur_interne
Une constante numérique qui précise la longueur en octets de la représentation interne du nouveau type. Supposée variable par défaut.
alignement
La spécification d'alignement du stockage du type de données. Peut être
char
, int2
,
int4
ou double
;
int4
par défaut.
stockage
La stratégie de stockage du type de données. Peut être plain
,
external
,
extended
ou main
;
plain
par défaut.
type_like
Le nom d'un type de données existant dont le nouveau type partagera la
représentation. Les valeurs de
longueurinterne
,
passedbyvalue
,
alignement
et
stockage
sont recopiées à
partir de ce type, sauf si elles sont écrasées explicitement ailleurs
dans la même commande CREATE TYPE
.
catégorie
Le code de catégorie (un unique caractère ASCII) pour ce type.
La valeur par défaut est U
pour
« user-defined type » (type défini par l'utilisateur).
Les autres codes standard de catégorie peuvent être trouvés dans
Tableau 51.65. Vous pouvez aussi choisir
d'autres caractères ASCII pour créer vos propres catégories personnalisées.
préféré
True si ce type est un type préféré dans sa catégorie de types, sinon false. La valeur par défaut est false. Faites très attention en créant un nouveau type préféré à l'intérieur d'une catégorie existante car cela pourrait créer des modifications surprenantes de comportement.
défaut
La valeur par défaut du type de données. Omise, elle est NULL.
élément
Type des éléments du type tableau créé.
délimiteur
Le caractère délimiteur des valeurs des tableaux de ce type.
collatable
Vrai si les opérations de ce type peuvent utiliser les informations de collationnement. Par défaut, à faux.
Comme il n'y a pas de restrictions à l'utilisation d'un type de données une fois qu'il a été créé, créer un type de base ou un type range est équivalent à donner les droits d'exécution sur les fonctions mentionnées dans la définition du type. Ce n'est pas un problème habituellement pour le genre de fonctions utiles dans la définition d'un type mais réfléchissez bien avant de concevoir un type d'une façon qui nécessiterait que des informations « secrètes » soient utilisées lors de sa convertion vers ou à partir d'une forme externe.
Avant PostgreSQL version 8.3, le nom d'un type
tableau généré était toujours exactement le nom du type élément avec un
caractère tiret bas (_
) en préfixe. (Les noms des types
étaient du coup limités en longueur à un caractère de moins que les autres
noms.) Bien que cela soit toujours le cas, le nom d'un type tableau peut
varier entre ceci dans le cas des noms de taille maximum et les collisions
avec des noms de type utilisateur qui commencent avec un tiret bas. Écrire
du code qui dépend de cette convention est du coup obsolète. À la place,
utilisez pg_type
.typarray
pour situer le type tableau associé avec un type donné.
Il est conseillé d'éviter d'utiliser des noms de table et de type qui commencent avec un tiret bas. Alors que le serveur changera les noms des types tableau générés pour éviter les collisions avec les noms donnés par un utilisateur, il reste toujours un risque de confusion, particulièrement avec les anciens logiciels clients qui pourraient supposer que les noms de type commençant avec un tiret bas représentent toujours des tableaux.
Avant PostgreSQL version 8.2, la syntaxe de
création d'un type shell
CREATE TYPE
n'existait pas.
La façon de créer un nouveau type de base était de créer en premier les
fonctions paramètres. Dans cette optique,
PostgreSQL verra tout d'abord le nom d'un nouveau
type de données comme type de retour de la fonction en entrée. Le type shell
est créé implicitement dans ce cas et il est ensuite référencé dans le reste
des fonctions d'entrée/sortie. Cette approche fonctionne toujours mais
est obsolète et pourrait être interdite dans une version future. De plus,
pour éviter de faire grossir les catalogues de façon accidentelle avec des
squelettes de type erronés, un squelette sera seulement créé quand la fonction
en entrée est écrit en C.
nom
À partir de PostgreSQL 16, il est préférable
que les fonctions en entrée des types de base renvoient des erreurs
« douces » en utilisant le nouveau mécanisme
errsave()
/ereturn()
plutôt qu'en renvoyant des exceptions ereport()
comme dans les versions précédentes. Voir
src/backend/utils/fmgr/README
pour plus
d'informations.
Créer un type composite utilisé dans la définition d'une fonction :
CREATE TYPE compfoo AS (f1 int, f2 text); CREATE FUNCTION getfoo() RETURNS SETOF compfoo AS $$ SELECT fooid, fooname FROM foo $$ LANGUAGE SQL;
Cet exemple crée un type énuméré et l'utilise dans la création d'une table :
CREATE TYPE statut_bogue AS ENUM ('nouveau', 'ouvert', 'fermé'); CREATE TABLE bogue ( id serial, description text, status statut_bogue );
Cet exemple crée un type intervalle :
CREATE TYPE float8_range AS RANGE (subtype = float8, subtype_diff = float8mi);
Créer le type de données basique box
utilisé dans
la définition d'une table :
CREATE TYPE box; CREATE FUNCTION ma_fonction_entree_box(cstring) RETURNS box AS ... ; CREATE FUNCTION ma_fonction_sortie_box(box) RETURNS cstring AS ... ; CREATE TYPE box ( INTERNALLENGTH = 16, INPUT = ma_fonction_entree_box, OUTPUT = ma_fonction_sortie_box ); CREATE TABLE myboxes ( id integer, description box );
Si la structure interne de box
est un tableau de quatre
éléments float4
, on peut écrire :
CREATE TYPE box ( INTERNALLENGTH = 16, INPUT = ma_fonction_entree_box, OUTPUT = ma_fonction_sortie_box, ELEMENT = float4 );
ce qui permet d'accéder aux nombres composant la valeur d'une boîte par les indices. Le comportement du type n'est pas modifié.
Créer un objet large utilisé dans la définition d'une table :
CREATE TYPE bigobj ( INPUT = lo_filein, OUTPUT = lo_fileout, INTERNALLENGTH = VARIABLE ); CREATE TABLE big_objs ( id integer, obj bigobj );
D'autres exemples, intégrant des fonctions utiles d'entrée et de sortie, peuvent être consultés dans Section 36.13.
La première forme de la commande CREATE TYPE
, qui crée
un type composite, est conforme au standard SQL. Les
autres formes sont des extensions de PostgreSQL.
L'instruction CREATE TYPE
du standard
SQL définit aussi d'autres formes qui ne sont pas
implémentées dans PostgreSQL.
La possibilité de créer un type composite sans attributs est une différence
spécifique de PostgreSQL que le standard ne
propose pas (de façon analogue au CREATE TABLE
).