sql >> Database >  >> RDS >> PostgreSQL

Unieke combinaties opslaan en vergelijken

Opslaan als array (gedenormaliseerd)

Ik zou de aanvullende module intarray overwegen die de handige (en snelle) functies biedt uniq() en sort() . In een typische moderne Postgres-installatie is het zo eenvoudig als:

CREATE EXTENSION intarray;

Met behulp van deze, een eenvoudige CHECK beperking kan oplopend afdwingen arrays met onderscheiden elementen.

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

U kunt aanvullend (optioneel) een trigger hebben die arraywaarden normaliseert ON INSERT OR UPDATE automatisch. Dan kun je gewoon elke doorgeven array (mogelijk ongesorteerd en met dupes) en alles werkt gewoon. Vind ik leuk:

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

De extra module intarray is optioneel, er zijn andere manieren:

Maar de intarray-functies leveren superieure prestaties.

Dan je kunt gewoon een UNIQUE . maken beperking op de matrixkolom om de uniciteit van de hele matrix af te dwingen.

UNIQUE (cat_arr)

Twee dagen geleden schreef ik in dit gerelateerde antwoord meer over de voordelen van het combineren van (zeer strikte en betrouwbare) beperkingen met (minder betrouwbare maar handigere) triggers:

Als je voor elke combinatie alleen de ID hoeft op te slaan (en geen aanvullende informatie), zou dit goed genoeg moeten zijn.
Echter referentiële integriteit is op deze manier niet gemakkelijk te waarborgen. Er zijn (nog) geen externe sleutelbeperkingen voor array-elementen - zoals gedocumenteerd in uw link :Als een van de categorieën wordt verwijderd of als u ID's wijzigt, worden verwijzingen verbroken ...

Genormaliseerd schema

Als u meer moet opslaan of liever een genormaliseerd schema gebruikt om referentiële integriteit af te dwingen of om een ​​of andere reden, kunt u dat ook doen en een trigger toevoegen om een ​​handgemaakte gematerialiseerde weergave (een redundante tabel) te vullen en uniciteit op een vergelijkbare manier afdwingen:

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

Gerelateerd antwoord (niet voor unieke combinaties, maar voor unieke elementen) dat de trigger demonstreert:



  1. Vervang dubbele spaties door een enkele spatie in T-SQL

  2. Hoe de tabel automatisch bij te werken in MYSQL met behulp van TRIGGER

  3. Logica voor reeds bestaande recordcontrole, maar alleen in het geval van bijgewerkte formulierwaarden

  4. Bulk postgres invoegen waar tijdstempel een null-beperking heeft ingesteld via sequalize