web-dev-qa-db-fra.com

Postgresql insert trigger to set value

Supposons que dans Postgresql, j'ai une table T et une de ses colonnes est C1.

Je veux déclencher une fonction lorsqu'un nouvel enregistrement est ajouté à la table T. La fonction doit vérifier la valeur de la colonne C1 dans le nouvel enregistrement et s'il est nul/vide, définissez sa valeur sur 'X'.

Est-ce possible?

49
user1408470

Vous avez raison, vous avez besoin d'un déclencheur, car la définition d'une valeur par défaut pour la colonne ne fonctionnera pas pour vous - les valeurs par défaut ne fonctionnent que pour les valeurs null et ne vous aident pas à empêcher les valeurs vides.

Dans postgres, il existe quelques étapes pour créer un déclencheur:

Étape 1: créez une fonction qui renvoie le type trigger:

CREATE FUNCTION my_trigger_function()
RETURNS trigger AS '
BEGIN
  IF NEW.C1 IS NULL OR NEW.C1 = '''' THEN
    NEW.C1 := ''X'';
  END IF;
  RETURN NEW;
END' LANGUAGE 'plpgsql'

Étape 2: Créez un déclencheur qui se déclenche avant l'insertion , qui vous permet de modifier les valeurs avant leur insertion, qui invoque la fonction ci-dessus:

CREATE TRIGGER my_trigger
BEFORE INSERT ON T
FOR EACH ROW
EXECUTE PROCEDURE my_trigger_function()

Et tu as fini.

Voir le code ci-dessus s'exécutant sur SQLFIddle démontrant qu'il fonctionne correctement!


Vous mentionnez dans un commentaire que la valeur 'X' est extrait d'une sous-requête. Si tel est le cas, modifiez la ligne appropriée pour quelque chose comme:

NEW.C1 := (select some_column from some_table where some_condition);
77
Bohemian

C'est possible, mais vous feriez mieux de définir une contrainte par défaut sur la colonne à la place. Lors de la création de la table qui ressemblerait à:

create table mytable as (
    C1 thetype not null default X
);

Cela signifie que si vous ajoutez une ligne à la table et ne spécifiez pas la valeur pour C1, X sera utilisé à la place. La valeur non nulle n'est pas nécessaire, mais empêche les mises à jour d'annuler cette colonne en supposant que c'est ce que vous voulez.

EDIT: Cela ne fonctionne que pour X constant, d'après vos commentaires, il semble qu'il y ait deux solutions possibles.

L'utilisation d'un déclencheur ressemblerait à ceci:

create function update_row_trigger() returns trigger as $$
begin
    if new.C1 is NULL then
        new.C1 := X;
    end if;
    return new;
end
$$ language plpgsql;

create trigger mytrigger before insert on mytable for each row execute procedure update_row_trigger();

La variable new dans une fonction de déclenchement est spéciale, représentant la ligne insérée. Spécification du déclencheur en tant que before insert trigger signifie que vous pouvez modifier la ligne avant qu'elle ne soit écrite dans la table.

La deuxième solution serait d'utiliser une colonne calculée que Postgres définit de manière inhabituelle:

create or replace function C1(row mytable) returns columntype immutable as $$
begin
    return X; -- where X is an expression using values from `row`
end
$$ language plpgsql;

Cela crée une fonction qui prend une ligne de votre table et renvoie une valeur, vous pouvez l'appeler en utilisant. la notation cependant, ce qui signifie que vous pouvez faire:

select
    *,
    t.C1
from
    mytable t;

La déclaration de la fonction immuable est facultative, mais elle est nécessaire si vous souhaitez indexer la "colonne". Vous pourriez indexer cette colonne comme ceci:

create index on mytable (C1(mytable));
9
Steve