2013-04-08 11 views
13
CREATE TABLE foo (
    dt  AS DATE NOT NULL, 
    type AS TEXT NOT NULL, 
    CONSTRAINT unique_dt_type UNIQUE(dt,type) -- check constraint(?) 
) 

Posiadanie niedoboru mózgów, gdy próbuje się wymyślić właściwą składnię, aby stworzyć wyjątkowe ograniczenie, gdy istnieje tylko pewien warunek.SQL: Niepowtarzalne ograniczenie, gdy kolumna ma określoną wartość:

Podane, type może mieć wartości A-F, może być tylko jeden A na datę, ale może być wiele B-F. Przykład dobrej tabeli:

2010-01-02 | 'A' -- only one 
2010-01-02 | 'B' -- can have multiple 
2010-01-02 | 'B' 
2010-01-02 | 'B' 
2010-01-02 | 'C' -- can have multiple 
2013-01-02 | 'A' -- only one 
2010-01-02 | 'B' -- can have multiple 
2010-01-02 | 'B' 
2013-01-02 | 'F' -- can have multiple 
2013-01-02 | 'F' 

Próbowano sprawdzić czytanie/unikalną składnię, ale nie było żadnych przykładów. CHECK podszedł blisko, ale ograniczył go do zakresu i nie był używany w połączeniu ze scenariuszem UNIQUE. Próbowałem również wyszukiwania, ale moje umiejętności wyszukiwania są albo nie do normy, albo nie ma podobnych pytań.

+0

Można to zrobić za pomocą easely spust! – Houari

+0

@Houari: Brzmi obiecująco, czy masz szybki przykład? Znalazłem pewne wyniki, gdy szukałem 'sql conditional unique', ale bez powodzenia (były datowane) – vol7ron

+1

Być może znalazłem rozwiązanie w pytaniu tutaj: http://stackoverflow.com/q/987099/183181, jeśli 'where' jest dozwolone podczas tworzenia indeksu – vol7ron

Odpowiedz

17

PostgreSQL może zaspokoić Twoje potrzeby dzięki funkcji "Częściowy indeks". W praktyce jest to realizowane przez dodanie klauzuli where do instrukcji tworzenia indeksu.

Próbka:

CREATE INDEX my_partial_ix ON my_sample_table (my_sample_field) 
WHERE NOT (my_sample_field = 'duplicates ok'); 

Spójrz tutaj: http://www.postgresql.org/docs/current/interactive/indexes-partial.html

zwrócić szczególną uwagę na odcinku Example 11-3. Setting up a Partial Unique Index. Daje przykład, który dobrze komponuje się z określonym celem.

1

Korzystanie wyzwalacz:

CREATE OR REPLACE FUNCTION "CheckConstraint"() 
    RETURNS trigger AS 
$BODY$declare 
already_exists boolean; 
begin 

if new.foo_type='A' then 
select count(*) >0 from foo where foo_type='A' and dt=new.dt INTO already_exists; 
if already_exists then 
raise exception 'date % already have an A', new.dt; 
end if; 
end if; 

return new; 
end;$BODY$ 
    LANGUAGE plpgsql VOLATILE 
    COST 100; 
+2

Way zbyt skomplikowane. Nie skaluje się, a używanie częściowego indeksu jest znacznie szybsze i bardziej niezawodne. –

+0

Ponadto indeks automatycznie przyspiesza dopasowywanie zapytań. Tylko niewielka wada: indeks potrzebuje trochę miejsca na dysku. –

Powiązane problemy