sql >> Databasteknik >  >> RDS >> PostgreSQL

Composite PRIMARY KEY upprätthåller NOT NULL-begränsningar på inblandade kolumner

Om du behöver för att tillåta NULL-värden, använd en UNIQUE begränsning istället för en PRIMARY KEY (och lägg till en surrogat-PK-kolumn, jag föreslår en serial ). Detta tillåter kolumner att vara NULL:

CREATE TABLE distributor (
   distributor_id serial PRIMARY KEY
 , m_id integer
 , x_id integer
 , UNIQUE(m_id, x_id)
);

Obs , dock (per dokumentation):

I syfte att skapa en unik begränsning anses null-värden inte vara lika.

I ditt fall kan du ange något som (1, NULL) för (m_id, x_id) valfritt antal gånger utan att bryta mot begränsningen. Postgres anser aldrig två NULL-värden lika - enligt definition i SQL-standarden.

Om du behöver behandla NULL värden är lika för att inte tillåta sådana "dubbletter", Jag ser två alternativ :

1. Två partiella index

Dessutom till UNIQUE begränsning ovan:

CREATE UNIQUE INDEX dist_m_uni_idx ON distributor (m_id) WHERE x_id IS NULL;
CREATE UNIQUE INDEX dist_x_uni_idx ON distributor (x_id) WHERE m_id IS NULL;

Men detta går snabbt ur händerna med mer än två kolumner som kan vara NULL. Se:

  • Skapa en unik begränsning med nollkolumner

2. En flerkolumn UNIQUE index på uttryck

Istället för den UNIKA begränsningen. Vi behöver ett gratis standardvärde som aldrig finns i involverade kolumner, som -1 . Lägg till CHECK begränsningar för att inte tillåta det:

CREATE TABLE distributor (
   distributor serial PRIMARY KEY
 , m_id integer
 , x_id integer
 , CHECK (m_id &lt> -1)
 , CHECK (x_id &lt> -1)
);
CREATE UNIQUE INDEX distributor_uni_idx ON distributor (COALESCE(m_id, -1)
                                                      , COALESCE(x_id, -1))

Hur vissa RDBMS hanterar saker är inte alltid en användbar indikator för korrekt beteende. Postgres-manualen tipsar om detta:

Det betyder att även i närvaro av en unik begränsning är det möjligt att lagra dubbletter av rader som innehåller ett nollvärde i minst en av de begränsade kolumnerna. Detta beteende överensstämmer med SQL-standarden, men vi har hört att andra SQL-databaser kanske inte följer denna regel .Så var försiktig när du utvecklar applikationer som är avsedda att vara portabla.

Djärv betoning min.




  1. Java SQLData - Casta till användarobjekt med en lista/array?

  2. MariaDB CURRENT_USER() Förklarad

  3. Postgres datum överlappande begränsning

  4. Konvertera från MySQL datetime till ett annat format med PHP