CREATE RULE — Définir une nouvelle règle de réécriture
CREATE [ OR REPLACE ] RULE nom AS ON événement TO nom_table [ WHERE condition ] DO [ ALSO | INSTEAD ] { NOTHING | commande | ( commande ; commande ... ) }
CREATE RULE définit une nouvelle règle sur une table ou une vue. CREATE OR REPLACE RULE crée une nouvelle règle ou remplace la règle si elle existe déjà.
Le système de règles de PostgreSQL™ autorise la définition d'actions alternatives sur les insertions, mises à jour ou suppressions dans les tables. Pour résumer, une règle impose des commandes supplémentaires lors de l'exécution d'une instruction sur une table donnée. Une règle INSTEAD, au contraire, permet de remplacer une commande par une autre, voire d'empêcher sa réalisation. Ce sont également les règles qui sont utilisées pour implanter les vues.
Une règle est un mécanisme de transformation de commandes, une « macro ». La transformation intervient avant l'exécution de la commande. Pour obtenir une opération qui s'exécute indépendamment pour chaque ligne physique, il faut utiliser des déclencheurs. On trouvera plus d'informations sur le système des règles dans Chapitre 38, Système de règles.
À l'heure actuelle, les règles ON SELECT doivent être des règles INSTEAD inconditionnelles. Chacune de leurs actions ne peut être constituée que d'une simple commande SELECT. Ainsi, une règle ON SELECT a pour résultat la transformation effective d'une table en une vue dont le contenu visible est composé des lignes retournées par la commande SELECT de la règle ; ce ne sont pas les lignes stockées dans la table (s'il y en a) qui sont retournées. Le création d'une vue à l'aide de la commande CREATE VIEW est toujours préférable à la création d'une table réelle associée à une règle ON SELECT.
On peut donner l'illusion d'une vue actualisable (« updatable view ») par la définition de règles ON INSERT, ON UPDATE et ON DELETE (ou tout sous-ensemble de celles-ci) pour remplacer les actions de mises à jour de la vue par des mises à jours des tables adéquates. Si vous voulez supporter INSERT RETURNING, alors assurez-vous de placer une clause RETURNING adéquate à chacune de ces règles.
Il y a quelques chausse-trappes à éviter lors de l'utilisation de règles conditionnelles pour la mise à jour de vues complexes : à chaque action autorisée sur la vue doit correspondre une règle INSTEAD inconditionnelle. Si la règle est conditionnelle ou n'est pas une règle INSTEAD, alors le système rejette toute tentative de mise à jour, ceci afin d'éviter toute action sur la table virtuelle de la vue. Pour gérer tous les cas utiles à l'aide de règles conditionnelles, il convient d'ajouter une règle inconditionnelle DO INSTEAD NOTHING afin de préciser au système qu'il ne recevra jamais de demande de mise à jour d'une table virtuelle. La clause INSTEAD des règles conditionnelles peut alors être supprimée ;dans les cas où ces règles s'appliquent, l'action INSTEAD NOTHING est utilisée. (Néanmoins, cette méthode ne fonctionne pas actuellement avec les requêtes RETURNING.)
Une vue qui est suffisamment simple pour être modifiable automatiquement (voir CREATE VIEW(7)) ne nécessite pas un règle utilisateur pour être modifiable. Bien que vous puissiez de toute façon créer une règle, la transformation automatique de la mise à jour sera généralement plus performante qu'une règle explicite.
Une autre alternative à considérer est l'utilisateur des triggers INSTEAD OF (voir CREATE TRIGGER(7)) à la place des règles.
Le nom de la règle à créer. Elle doit être distincte du nom de toute autre règle sur la même table. Les règles multiples sur la même table et le même type d'événement sont appliquées dans l'ordre alphabétique des noms.
SELECT, INSERT, UPDATE ou DELETE.
Le nom (éventuellement qualifié du nom du schéma) de la table ou de la vue sur laquelle s'applique la règle.
Toute expression SQL conditionnelle (renvoyant un type boolean). L'expression de la condition ne peut pas faire référence à une table autre que NEW ou OLD ni contenir de fonction d'agrégat.
Les commandes sont exécutées à la place de la commande originale.
Les commandes sont exécutées en plus de la commande originale.
En l'absence de ALSO et de INSTEAD, ALSO est utilisé par défaut.
Commande(s) réalisant l'action de la règle. Les commandes valides sont SELECT, INSERT, UPDATE, DELETE ou NOTIFY.
À l'intérieur d'une condition ou d'une commande, les noms des tables spéciales NEW et OLD peuvent être utilisés pour faire référence aux valeurs de la table référencée. NEW peut être utilisé dans les règles ON INSERT et ON UPDATE pour faire référence à la nouvelle ligne lors d'une insertion ou à la nouvelle valeur de la ligne lors d'une mise à jour. OLD est utilisé dans les règles ON UPDATE et ON DELETE pour référencer la ligne existant avant modification ou suppression.
Vous devez être le propriétaire de la table à créer ou sur laquelle vous ajoutez des règles.
Dans une règle pour l'action INSERT, UPDATE ou DELETE sur une vue, vous pouvez ajouter une clause RETURNING qui émet les colonnes de la vue. Cette clause sera utilisée pour calculer les sorties si la règle est déclenchée respectivement par une commande INSERT RETURNING, UPDATE RETURNINGou DELETE RETURNING. Quand la règle est déclenchée par une commande sans clause RETURNING, la clause RETURNING de la règle est ignorée. L'implémentation actuelle autorise seulement des règles INSTEAD sans condition pour contenir RETURNING ; de plus, il peut y avoir au plus une clause RETURNING parmi toutes les règles pour le même événement. (Ceci nous assure qu'il y a seulement une clause RETURNING candidate utilisée pour calculer les résultats.) Les requêtes RETURNING sur la vue seront rejetées s'il n'existe pas de clause RETURNING dans une des règles disponibles.
Une attention particulière doit être portée aux règles circulaires. Ainsi dans l'exemple suivant, bien que chacune des deux définitions de règles soit acceptée par PostgreSQL™, la commande SELECT produira une erreur à cause de l'expansion récursive de la règle :
CREATE RULE "_RETURN" AS ON SELECT TO t1 DO INSTEAD SELECT * FROM t2; CREATE RULE "_RETURN" AS ON SELECT TO t2 DO INSTEAD SELECT * FROM t1; SELECT * FROM t1;
Actuellement, si l'action d'une règle contient une commande NOTIFY, cette commande est exécutée sans condition, c'est-à-dire que NOTIFY est déclenché même si la règle ne s'applique à aucune ligne. Par exemple, dans :
CREATE RULE notify_me AS ON UPDATE TO matable DO ALSO NOTIFY matable; UPDATE matable SET name = 'foo' WHERE id = 42;
un événement NOTIFY est lancé durant un UPDATE, qu'il y ait ou non des lignes satisfaisant la condition id = 42. Cette restriction pourrait être corrigée dans les prochaines versions.