sql >> Databáze >  >> RDS >> PostgreSQL

Ukládání a porovnávání jedinečných kombinací

Uložit jako pole (denormalizované)

Zvažoval bych doplňkový modul intarray který poskytuje pohodlné (a rychlé) funkce uniq() a sort() . V typické moderní instalaci Postgres je to stejně snadné jako:

CREATE EXTENSION intarray;

Pomocí těchto jednoduchých CHECK omezení může vynutit vzestupně pole s výraznými prvky.

CHECK (uniq(sort(cat_arr)) = cat_arr)

Můžete dodatečně (volitelně) mít spouštěč, který normalizuje hodnoty pole ON INSERT OR UPDATE automaticky. Pak stačí předat jakýkoli pole (možná netříděné a s dupy) a všechno prostě funguje. Jako:

CREATE OR REPLACE FUNCTION trg_search_insup_bef()
  RETURNS trigger AS
$func$
BEGIN
   NEW.cat_arr := uniq(sort(NEW.cat_arr);
   RETURN NEW;
END
$func$ LANGUAGE plpgsql;

CREATE TRIGGER insup_bef
BEFORE INSERT OR UPDATE OF cat_arr ON search
FOR EACH ROW
EXECUTE PROCEDURE trg_search_insup_bef();

Přídavný modul intarray je volitelný, existují další způsoby:

Ale funkce intarray poskytují vynikající výkon.

Potom stačí vytvořit UNIQUE omezení ve sloupci pole, aby se vynutila jedinečnost celého pole.

UNIQUE (cat_arr)

Před dvěma dny jsem psal více o výhodách kombinace (velmi přísných a spolehlivých) omezení s (méně spolehlivými, ale pohodlnějšími) spouštěči v této související odpovědi:

Pokud pro každou kombinaci potřebujete pro každou kategorii uložit pouze ID (a žádné další informace), mělo by to stačit.
Nicméně , referenční integrita není tímto způsobem snadno zajištěna. Pro prvky pole (zatím) neexistují žádná omezení cizího klíče – jako zdokumentované ve vašem odkazu :Pokud je jedna z kategorií odstraněna nebo změníte ID, reference se přeruší ...

Normalizované schéma

Pokud potřebujete uložit více nebo byste raději použili normalizované schéma k vynucení referenční integrity nebo z nějakého důvodu, můžete to udělat také a přidat spouštěč pro naplnění ručně vytvořeného materializovaného pohledu (nadbytečná tabulka) a vynutit jedinečnost podobným způsobem:

CREATE TABLE search (
  search_id serial PRIMARY KEY
, ... more columns
);

CREATE TABLE cat (
  cat_id serial PRIMARY KEY
, cat text NOT NULL
);

CREATE TABLE search_cat (
  search_id int REFERENCES search ON DELETE CASCADE
, cat_id    int REFERENCES cat
, PRIMARY KEY (search_id, cat_id)
);

Související odpověď (ne pro jedinečné kombinace, ale pro jedinečné prvky), která demonstruje spouštěč:



  1. jak používat regexp_like Oracle v Hibernate HQL?

  2. Výsledky automatického doplňování textového pole na základě databáze SQL

  3. Jsou možné vlastní typy JPA (EclipseLink)?

  4. Má vytvoření a indexování na primárním klíči nějakou výhodu?