2013-04-19 17 views
30

Assumendo in Postgresql, ho una tabella T e una della sua colonna è C1.Postgresql inserire trigger per impostare il valore

Desidero attivare una funzione quando un nuovo record si aggiunge alla tabella T. La funzione dovrebbe verificare il valore della colonna C1 nel nuovo record e se è nullo/vuoto, impostare il suo valore su 'X'.

È possibile?

+0

Si noti che questo valore X deve essere recuperato da un'altra sottoquery. – user1408470

risposta

52

Lei ha ragione che avete bisogno di un trigger, perché l'impostazione di un valore predefinito per la colonna non funziona per voi - i valori di default funziona solo per null valori e non ti aiuta a prevenire valori vuoti.

In postgres ci sono un paio di passi per la creazione di un trigger:

Passaggio 1: Creare una funzione che restituisce tipo 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' 

Passaggio 2: Creare un trigger che spara prima inserto, che consente di modificare i valori befre sono inseriti, che richiama la funzione di cui sopra:

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

E il gioco è fatto.

Vedere the above code executing on SQLFIddle dimostrando che funziona correttamente!


si parla in un commento che il valore 'X' viene recuperato da una subquery. In tal caso, modificare la riga corrispondente in modo simile:

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

Grazie per la risposta. Questo è esattamente quello che volevo. – user1408470

+5

Perché non stai usando '$$' ma invece '''? – displayname

6

È possibile ma è probabile che sia preferibile impostare un vincolo predefinito sulla colonna. Quando si crea la tabella che sarà simile:

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

Questo dice che se si aggiunge una riga al tavolo e non si specifica il valore per C1 allora X sarà utilizzato al posto. Il non nullo non è necessario, ma impedisce agli aggiornamenti di annullare quella colonna assumendo che sia ciò che si desidera.

MODIFICA: funziona solo per X costante, dai tuoi commenti sembra che ci siano due soluzioni possibili.

Utilizzando un trigger sarebbe simile a questa:

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

Il new variabile in una funzione di trigger è speciale, che rappresenta la riga viene inserita. Specificare il trigger come trigger before insert significa che è possibile modificare la riga prima che venga scritta sulla tabella.

La seconda soluzione sarebbe quella di utilizzare una colonna calcolata che Postgres definisce in un modo insolito:

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; 

questo modo si crea una funzione che prende una riga della tabella e restituisce un valore, si può chiamare usando . notazione, però, il che significa che si può fare:

select 
    *, 
    t.C1 
from 
    mytable t; 

La dichiarazione della funzione di essere immutabili è facoltativo, ma è necessario se si vuole indicizzare la "colonna". Si sarebbe in grado di indicizzare questa colonna come questo:

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

Grazie, ma nel mio caso ottengo un errore quando si imposta il valore come vincolo predefinito. Perché questo valore X è ottenuto da una sottoquery quindi non è consentito. Puoi dirmi una soluzione. – user1408470

+0

Il valore di C1 è determinato in modo univoco dagli altri valori nella stessa riga o dipende da altri fattori come l'ora del giorno o i dati in altre tabelle? – Steve

+0

È determinato in modo univoco. semplicemente viene recuperato da (selezionare id da Table2 dove name = 'Unique_Value'). Questo ID può essere diverso in diversi DB, quindi è necessario recuperarlo sempre da una sottoquery. – user1408470

Problemi correlati