PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Przechowywanie i porównywanie unikalnych kombinacji

Przechowuj jako tablicę (zdenormalizowaną)

Rozważę dodatkowy moduł intarray który zapewnia wygodne (i szybkie) funkcje uniq() i sort() . W typowej nowoczesnej instalacji Postgresa jest to tak proste, jak:

CREATE EXTENSION intarray;

Korzystając z nich, proste CHECK ograniczenie może wymuszać wznoszące tablice z różnymi elementy.

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

Możesz dodatkowo (opcjonalnie) mieć wyzwalacz, który normalizuje wartości tablicy ON INSERT OR UPDATE automatycznie. Wtedy możesz po prostu przekazać dowolne tablica (prawdopodobnie nieposortowana iz duplikatami) i wszystko po prostu działa. Na przykład:

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

Dodatkowa intarray modułów jest opcjonalna, istnieją inne sposoby:

Ale funkcje intarray zapewniają doskonałą wydajność.

Wtedy możesz po prostu utworzyć UNIQUE ograniczenie w kolumnie tablicy, aby wymusić unikalność całej tablicy.

UNIQUE (cat_arr)

Pisałem więcej o zaletach łączenia (bardzo rygorystycznych i niezawodnych) ograniczeń z (mniej niezawodnymi, ale wygodniejszymi) wyzwalaczami w tej powiązanej odpowiedzi zaledwie dwa dni temu:

Jeśli dla każdej kombinacji wszystko, co musisz przechowywać w danej kategorii, to identyfikator (i żadnych dodatkowych informacji), powinno to wystarczyć.
Jednak , w ten sposób nie jest łatwo zapewnić integralność referencyjną. Nie ma ograniczeń kluczy obcych dla elementów tablicy (jeszcze) - jak udokumentowane w Twoim linku :Jeśli jedna z kategorii zostanie usunięta lub zmienisz identyfikatory, odniesienia zostaną przerwane ...

Znormalizowany schemat

Jeśli potrzebujesz przechowywać więcej lub wolisz korzystać ze znormalizowanego schematu, aby wymusić integralność referencyjną lub z jakiegoś powodu, możesz to zrobić również i dodać wyzwalacz, aby wypełnić ręcznie wykonany widok zmaterializowany (nadmiarowa tabela) i wymuszać unikalność w podobny sposób:

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

Powiązana odpowiedź (nie dla unikalnych kombinacji, ale dla unikalnych elementów), która demonstruje wyzwalacz:



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Parametr konfiguracyjny work_mem w PostgreSQL w systemie Linux

  2. Transponuj wiersze SQL jako kolumny

  3. Wdrażanie projektu Django na Webfaction

  4. Konwersja bazy danych Postgresql z SQL_ASCII, zawierającej mieszane typy kodowania, do UTF-8

  5. grupuj według przedziału cenowego