2013-04-19 13 views
30

Założono w Postgresql, mam tabelę T i jedną z jej kolumn jest C1.Wyzwalacz PostgreSQL do ustawiania wartości

Chcę uruchomić funkcję, gdy nowy rekord dodaje do tabeli T. Funkcja powinna sprawdzić wartość kolumny C1 w nowym rekordzie, a jeśli jest pusta/pusta, ustawić jej wartość na 'X'.

Czy to możliwe?

+0

Pl zwrócić uwagę, że ta wartość X musi zostać pobrana z innego podkwerendy. – user1408470

Odpowiedz

52

Masz rację, że trzeba spust, ponieważ ustawienie wartości domyślnych dla kolumny nie będzie pracować dla Ciebie - wartości domyślne działa tylko dla wartości i null nie pomagają w zapobieganiu pustym wartościom.

W PostgreSQL istnieje kilka kroków do tworzenia wyzwalacza:

Krok 1: Utwórz funkcję zwracającą typ 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' 

Krok 2: Utwórz wyzwalacz, który odpala przed insert, który pozwala zmienić wartości po ich wstawieniu, które wywołuje powyższą funkcję:

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

I gotowe.

Zobacz the above code executing on SQLFIddle pokazując, że działa poprawnie!


Możesz wspomnieć w komentarzu, że wartość 'X' są pobierane z podzapytania. Jeśli tak, zmień odpowiednią linię tak, aby coś w stylu:

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

Dzięki za odpowiedź. Właśnie tego chciałem. – user1408470

+5

Dlaczego nie używasz '$$', ale zamiast tego '' '? – displayname

6

Jest to możliwe, ale prawdopodobnie lepiej będzie ustawić domyślne ograniczenie dla kolumny. Podczas tworzenia tabeli, która będzie wyglądać następująco:

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

mówi to, że jeśli dodać wiersz do tabeli i nie określają wartości dla C1 to X będzie używany zamiast. Wartość "null" nie jest konieczna, ale zapobiega pobieraniu aktualizacji od kolumny, zakładając, że tego właśnie chcesz.

EDYCJA: Działa tylko dla stałej X, z twoich komentarzy wynika, że ​​są dwa możliwe rozwiązania.

Korzystanie wyzwalacz będzie wyglądać mniej więcej tak:

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

new zmienna w funkcji wyzwalania jest wyjątkowy, reprezentujący rząd jest włożona. Określenie wyzwalacza jako wyzwalacza before insert oznacza, że ​​można zmodyfikować wiersz, zanim zostanie zapisany w tabeli.

Drugim rozwiązaniem byłoby użyć kolumna obliczana który Postgres definiujący w niezwykły sposób:

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; 

Stwarza funkcję, która pobiera wiersz tabeli i zwraca wartość, można wywołać go za pomocą . notacja choć, dzięki czemu można zrobić:

select 
    *, 
    t.C1 
from 
    mytable t; 

Deklaracja funkcją jest niezmienna jest opcjonalne, ale jest to potrzebne, jeśli chcesz indeksować „kolumny”. Byłbyś w stanie indeksować kolumna ta tak:

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

Dzięki, ale w moim przypadku wystąpił błąd podczas ustawiania wartości jako domyślnego ograniczenia. Ponieważ ta wartość X jest pobierana przez podzapytanie, więc nie jest dozwolona. Czy możesz mi powiedzieć obejście. – user1408470

+0

Czy wartość C1 jest jednoznacznie określona przez inne wartości w tym samym wierszu lub czy zależy ona od innych czynników, takich jak pora dnia lub dane w innych tabelach? – Steve

+0

Jest jednoznacznie określone. po prostu jest pobierany przez (wybierz identyfikator z tabeli 2, gdzie name = "Unique_Value"). Identyfikator ten może się różnić w różnych DB, więc trzeba go zawsze pobrać z podkwerendy. – user1408470

Powiązane problemy