sql >> Databasteknik >  >> RDS >> PostgreSQL

Postgres-begränsning som säkerställer att en kolumn av många finns?

Uppdatering 2021-09-17 :Från och med idag ger gerardnll ett bättre svar (den bästa IMO) :

För att hjälpa människor att hitta den renaste lösningen rekommenderar jag att du röstar upp gerardnls svar .

(FYI, jag är samma person som ställde den ursprungliga frågan.)

Här är mitt ursprungliga svar från 2013

Här är en elegant lösning med två kolumner enligt "begränsningen -- en eller den andra kolumnen inte null" PostgreSQL-anslagstavla :

ALTER TABLE my_table ADD CONSTRAINT my_constraint CHECK (
  (column_1 IS NULL) != (column_2 IS NULL));

(Men ovanstående tillvägagångssätt är inte generaliserbart till tre eller fler kolumner.)

Om du har tre eller fler kolumner kan du använda sanningstabellsmetoden som illustreras av a_horse_with_no_name . Jag anser dock att följande är lättare att underhålla eftersom du inte behöver skriva ut de logiska kombinationerna:

ALTER TABLE my_table
ADD CONSTRAINT my_constraint CHECK (
  (CASE WHEN column_1 IS NULL THEN 0 ELSE 1 END) +
  (CASE WHEN column_2 IS NULL THEN 0 ELSE 1 END) +
  (CASE WHEN column_3 IS NULL THEN 0 ELSE 1 END) = 1;

För att komprimera detta skulle det vara användbart att skapa en anpassad funktion så att CASE WHEN column_k IS NULL THEN 0 ELSE 1 END pannplattan kan tas bort och lämna något i stil med:

(non_null_count(column_1) +
non_null_count(column_2) +
non_null_count(column_3)) = 1

Det kan vara så kompakt som PSQL tillåter (?). Som sagt, jag föredrar att komma till den här typen av syntax om möjligt:

non_null_count(column_1, column_2, column_3) = 1


  1. Kortslutningslogikutvärderingsoperatörer

  2. MySQL - FEL 1045 - Åtkomst nekad

  3. Extrahera en fullständig tidsstämpel (inkluderat datum) från en Select-fråga; Orakel

  4. Sök över en kapslad/multi-level Postgres JSON-typ med Active Record