Odpowiedz

22

to niemożliwe z prostym DEFAULT wartości, gdyż the manual clearly states:

Wartość ta jest dowolna zmienna wolne ekspresji (podzapytania i odsyłacze do innych kolumn w bieżącej tablicy, nie są dozwolone).

można użyć trigger zamiast:

CREATE OR REPLACE FUNCTION trg_foo_b_default() 
    RETURNS trigger AS 
$func$ 
BEGIN 

-- For just a few constant options, CASE does the job: 
NEW.b := 
    CASE NEW.a 
    WHEN 'peter' THEN 'doctor' 
    WHEN 'weirdo' THEN 'shrink' 
    WHEN 'django' THEN 'undertaker' 
    ELSE NULL 
    END; 

/* -- For more, or dynamic options, you could use a lookup table: 
SELECT INTO NEW.b t.b 
FROM def_tbl t 
WHERE t.a = NEW.a; 
*/ 

RETURN NEW; 

END 
$func$ LANGUAGE plpgsql; 

CREATE TRIGGER b_default 
BEFORE INSERT ON foo 
FOR EACH ROW 
WHEN (NEW.b IS NULL AND NEW.a IS NOT NULL) 
EXECUTE PROCEDURE trg_foo_b_default(); 

Aby to bardziej skuteczne używam WHEN klauzuli (dostępna od PostgreSQL 9.0) z definicji wyzwalacza. W ten sposób funkcja wyzwalacza jest wykonywana tylko wtedy, gdy jest rzeczywiście przydatna. Zakładam, że możemy pozwolić, aby b IS NULL przesuwał się, jeśli a IS NULL.

Działa w podobnym, ale subtelnie innym mody z wartości DEFAULT.
Przy wartości domyślnej można jawnie wstawić NULL, aby anulować wartość domyślną. To niemożliwe tutaj, NULL w b jest zastąpione wartością pochodzącą z a.

+0

Dzięki za dopracowaną i zwięzłą odpowiedź – mosid