HiveBrain v1.2.0
Get Started
← Back to all entries
patternsqlMinor

Restrict two specific column values from existing at the same time

Submitted by: @import:stackexchange-dba··
0
Viewed 0 times
samethecolumnexistingtimetwospecificvaluesrestrictfrom

Problem

I have a PostgreSQL example table where at most one row that is not of type 'c' should be allowed.

I would appreciate any help creating a constraint that will enforce this.

CREATE TABLE example
(
  example_id    serial PRIMARY KEY,
  example_state CHAR(1) NOT NULL
);

ALTER TABLE example ADD CONSTRAINT 
  example_constraint
CHECK (example_state = 'a' OR example_state = 'b' OR example_state = 'c');

Solution

One row per rare type

If you want to allow 0-n rows with type 'c' and only 0-1 rows for type 'a' and 'b' (each), you can combine a simple CHECK constraint with a partial unique index:

CREATE TABLE example (
  example_id    serial PRIMARY KEY,
  example_state "char" NOT NULL CHECK (example_state IN ('a', 'b', 'c'))
);

CREATE UNIQUE INDEX example_unique_exception_idx ON example (example_state)
WHERE example_state <> 'c'; -- column is not null;


Related answer:

  • PostgreSQL multi-column unique constraint and NULL values



An exlusion constraint would be a related concept, but it won't work with multiple entries for 'c'. You could use NULL instead of 'c' to make that work.

  • Preventing adjacent/overlapping entries with EXCLUDE in PostgreSQL



Also note the special data type "char" (in double-quotes!), which seems to be perfect for your simple purpose (unless it's just a simplification for the purpose of the question). It only occupies a single byte - as opposed to char(1), which needs at least 2 bytes on disk and 5 in RAM.
Singleton row with any rare type

To restrict to a single row overall that does not have type 'c', use a partial unique index on an expression:

CREATE UNIQUE INDEX example_single_exception_idx ON example ((example_state <> 'c'))
WHERE example_state <> 'c';

Code Snippets

CREATE TABLE example (
  example_id    serial PRIMARY KEY,
  example_state "char" NOT NULL CHECK (example_state IN ('a', 'b', 'c'))
);

CREATE UNIQUE INDEX example_unique_exception_idx ON example (example_state)
WHERE example_state <> 'c'; -- column is not null;
CREATE UNIQUE INDEX example_single_exception_idx ON example ((example_state <> 'c'))
WHERE example_state <> 'c';

Context

StackExchange Database Administrators Q#73125, answer score: 6

Revisions (0)

No revisions yet.