2013-04-19 14 views
30

Angenommen, in Postgresql habe ich eine Tabelle T und eine seiner Spalte ist C1.Postgresql Trigger einfügen, um den Wert

Ich möchte eine Funktion auslösen, wenn ein neuer Datensatz der Tabelle T hinzugefügt wird. Die Funktion sollte den Wert der Spalte C1 im neuen Datensatz überprüfen. Wenn sie null/leer ist, legen Sie ihren Wert auf 'X' fest.

Ist das möglich?

+0

Bitte beachten Sie, dass dieser Wert X von einer anderen Unterabfrage abgerufen werden muss. – user1408470

Antwort

52

Sie sind richtig, dass Sie einen Trigger benötigen, weil Sie einen Standardwert für die Spalte Einstellung wird nicht für Sie arbeiten - Standardwerte nur für null Werte arbeiten und hilft dir nicht, leere Werte zu verhindern.

In postgres gibt es ein paar Schritte mit einer Trigger erstellen:

Schritt 1: eine Funktion erstellen, die Art liefert 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' 

Schritt 2: einen Trigger erstellen, die vor feuert Einfügen, mit dem Sie die Werte vor dem Einfügen ändern können. Dadurch wird die oben genannte Funktion aufgerufen:

Und du bist fertig.

Siehe the above code executing on SQLFIddle und zeigt, dass es richtig funktioniert!


Sie erwähnen in einem Kommentar, dass der Wert 'X' aus einer Unterabfrage abgerufen wird. Wenn dies der Fall ist, ändern Sie die relevante Zeile, z. B. wie folgt:

NEW.C1 := (select some_column from some_table where some_condition); 
+1

Danke für die Antwort. Genau das wollte ich. – user1408470

+5

Warum benutzen Sie nicht '$$', sondern '' '? – displayname

6

Es ist möglich, aber es ist wahrscheinlich besser, wenn Sie stattdessen eine Standardeinschränkung für die Spalte festlegen. Wenn die Tabelle erstellen, würde wie folgt aussehen:

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

, dass dies sagt, wenn Sie eine Zeile in der Tabelle hinzufügen, und geben Sie nicht den Wert für C1 dann wird X stattdessen verwendet werden. Das not null ist nicht notwendig, verhindert aber, dass Updates diese Spalte annullieren, vorausgesetzt, dass dies das ist, was Sie wollen.

EDIT: Dies funktioniert nur für konstante X, aus Ihren Kommentaren scheint es gibt zwei mögliche Lösungen.

Auslöser verwendet in etwa so aussehen:

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(); 

Die new Variable in einer Triggerfunktion ist speziell, als Vertreter der Reihe eingeführt wird. Wenn Sie den Trigger als before insert-Trigger angeben, können Sie die Zeile ändern, bevor sie in die Tabelle geschrieben wird.

Die zweite Lösung wäre eine berechnete Spalte zu verwenden, die Postgres auf ungewöhnliche Weise definiert:

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; 

eine Funktion Dies erzeugt, die eine Zeile der Tabelle nimmt und einen Wert zurückgibt, können Sie es nennen mit . Notation aber, was bedeutet, Sie tun können:

select 
    *, 
    t.C1 
from 
    mytable t; 

Die Deklaration der Funktion unveränderlich zu sein, ist optional, aber es benötigt wird, wenn Sie indizieren wollen die „Spalte“. Sie würden diese Spalte wie folgt Index der Lage sein:

create index on mytable (C1(mytable)); 
+0

Danke, aber in meinem Fall erhalte ich einen Fehler, wenn ich den Wert als Standard-Einschränkung festlege. Weil dieser Wert X von einer Unterabfrage erhalten wird, ist es nicht erlaubt. Können Sie mir bitte einen Workaround sagen. – user1408470

+0

Wird der Wert von C1 durch die anderen Werte in derselben Zeile eindeutig bestimmt oder hängt er von anderen Faktoren wie der Tageszeit oder Daten in anderen Tabellen ab? – Steve

+0

Es ist eindeutig festgelegt. einfach wird es abgerufen von (ID aus Table2 auswählen, wobei name = 'Unique_Value'). Diese ID kann in verschiedenen DBs unterschiedlich sein und muss daher immer von einer Unterabfrage abgerufen werden. – user1408470

Verwandte Themen