Une colonne générée est une colonne spéciale, toujours calculée à partir d'autres colonnes. Elle est donc aux colonnes ce qu'une vue est aux tables. Il y a deux types de colonnes générées : stockée et virtuelle. Une colonne générée stockée est calculée quand elle est écrite (insérée ou mise à jour) et occupe de l'espace de stockage comme si elle était une colonne normale. Une colonne virtuelle générée n'occupe pas d'espace et est calculée à la lecture. Une colonne générée virtuelle est donc équivalente à une vue, et une colonne générée stockée est équivalente à une vue matérialisée (sauf qu'elle sera toujours mise à jour automatiquement). PostgreSQL n'implémente actuellement que les colonnes générées stockées.
Pour créer une colonne générée, utilisez la clause GENERATED
ALWAYS AS
de la commande CREATE TABLE
, par
exemple :
CREATE TABLE people (
...,
height_cm numeric,
height_in numeric GENERATED ALWAYS AS (height_cm / 2.54) STORED
);
Le mot-clé STORED
doit ĂȘtre spĂ©cifiĂ© pour choisir le
type de colonne générée. Voir CREATE TABLE pour plus
de détails.
On ne peut écrire directement dans une colonne générée. Une valeur ne peut
pas y ĂȘtre affectĂ©e dans les commandes INSERT
ou
UPDATE
, mais le mot-clé DEFAULT
peut
l'ĂȘtre.
Voyons les différences entre une colonne avec une valeur par défaut et une
colonne générée. La colonne par défaut est calculée une seule fois à la
premiĂšre insertion de la ligne si aucune autre valeur n'est fournie ;
une colonne générée est mise à jour à chaque fois que la ligne change et
on ne peut y déroger. Une valeur par défaut d'une colonne ne peut se
référer à d'autres colonnes de la table ; mais c'est ce que fait
normalement une expression générée. Une valeur par défaut d'une colonne
peut utiliser des fonctions volatiles, par exemple
random()
ou des fonctions se référant au temps
actuel ; ce n'est pas permis pour les colonnes générées.
Il existe plusieurs restrictions dans la définition des colonnes générées et des tables qui les utilisent :
L'expression pour gĂ©nĂ©rer les valeurs ne peut utiliser que des fonctions immutables, ne peut pas utiliser de sous-requĂȘtes, ni rĂ©fĂ©rencer d'aucune maniĂšre quoi que ce soit hors de la ligne en cours.
Une expression ne peut référencer une autre colonne générée.
Une expression ne peut référencer une colonne systÚme, sauf
tableoid
.
Une colonne gĂ©nĂ©rĂ©e ne peut avoir une valeur par dĂ©faut ou ĂȘtre dĂ©finie comme colonne identitĂ©.
Une colonne générée ne peut faire partie d'une clé de partitionnement.
Les tables distantes peuvent porter des colonnes générées. Voir CREATE FOREIGN TABLE pour les détails.
Pour l'héritage et le partitionnement :
Si une colonne parent est une colonne gĂ©nĂ©rĂ©e, la colonne enfant doit aussi ĂȘtre une colonne gĂ©nĂ©rĂ©e ; nĂ©anmoins, la colonne enfant peut avoir une expression de gĂ©nĂ©ration diffĂ©rente. L'expression de gĂ©nĂ©ration qui est rĂ©ellement appliquĂ©e lors de l'insertion ou de la mise Ă jour d'une ligne est celle qui est associĂ©e avec la table qui contiendra physiquement la ligne. (Ceci est contraire au comportement pour la valeur par dĂ©faut d'une colonne : pour ces derniĂšres, la valeur par dĂ©faut appliquĂ©e est celle associĂ©e avec la table nommĂ©e dans la requĂȘte.)
Si une colonne parent n'est pas une colonne gĂ©nĂ©rĂ©e, sa colonne enfant ne doit pas non plus ĂȘtre une colonne gĂ©nĂ©rĂ©e.
Pour les tables héritées, si vous écrivez une définition de colonne
de la table enfant sans clause
GENERATED
dans CREATE TABLE
... INHERITS
, alors sa clause GENERATED
sera automatiquement copiée du parent. ALTER TABLE
... INHERIT
insistera que les colonnes parents et enfants
correspondant déjà au statut de génération, mais il n'obligera pas
à ce que les expressions de génération correspondent.
De façon similaire pour les tables partitionnées, si vous écrivez la
définition d'une colonne enfant sans la clause
GENERATED
clause dans
CREATE TABLE ... PARTITION OF
, alors la clause
GENERATED
sera automatiquement copiée du parent.
ALTER TABLE ... ATTACH PARTITION
insistera pour
que les colonnes parents et enfants correspondent déjà au niveau
du statut de génération, mais il ne reclamera pas que les expressions
de génération correspondent.
Dans le cas de plusieurs hĂ©ritages, si une des colonnes parents est une colonne gĂ©nĂ©rĂ©e, alors toutes les colonnes parents doivent ĂȘtre des colonnes gĂ©nĂ©rĂ©es. Si elles n'ont pas toutes la mĂȘme expression de gĂ©nĂ©ration, alors l'expression dĂ©sirĂ©e pour l'enfant doit ĂȘtre indiquĂ©e explicitement.
D'autres considérations s'appliquent à l'utilisation des colonnes générées.
Les colonnes générées maintiennent les droits d'accÚs séparément des colonnes sur lesquelles elles sont basées. On peut donc s'arranger pour qu'un rÎle défini puisse lire une colonne générée mais pas la colonne de base sous-jacente.
Conceptuellement, les colonnes générées sont mises à jour aprÚs le
déclenchement des triggers BEFORE
. Les changements
dans les colonnes de base au sein d'un trigger
BEFORE
seront donc répercutés dans les colonnes
générées. Mais à l'inverse, il n'est pas permis d'accéder aux colonnes
générées dans les triggers BEFORE
.
Les colonnes générées sont ignorées pour la réplication logique et ne
peuvent pas ĂȘtre indiquĂ©es dans une liste de colonnes d'une commande
CREATE PUBLICATION
.