sql >> Database teknologi >  >> RDS >> PostgreSQL

Composite PRIMARY KEY håndhæver NOT NULL-begrænsninger på involverede kolonner

Hvis du bruger for at tillade NULL-værdier skal du bruge en UNIQUE begrænsning i stedet for en PRIMARY KEY (og tilføje en surrogat-PK-kolonne, jeg foreslår en serial ). Dette tillader kolonner at være NULL:

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

Bemærk dog (pr. dokumentation):

Med henblik på en unik begrænsning anses null-værdier ikke for at være ens.

I dit tilfælde kan du indtaste noget som (1, NULL) for (m_id, x_id) et vilkårligt antal gange uden at overtræde begrænsningen. Postgres betragter aldrig to NULL-værdier som lige - som per definition i SQL-standarden.

Hvis du har brug for at behandle NULL værdier som lig for at ikke tillade sådanne "duplikater", Jeg ser to muligheder :

1. To delvise indekser

Desuden til UNIQUE begrænsning ovenfor:

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 dette kommer hurtigt ud af hænderne med mere end to kolonner, der kan være NULL. Se:

  • Opret en unik begrænsning med null-kolonner

2. En multi-kolonne UNIQUE indeks på udtryk

I stedet for den UNIKKE begrænsning. Vi har brug for en gratis standardværdi, der aldrig er til stede i involverede kolonner, såsom -1 . Tilføj CHECK begrænsninger for at ikke tillade 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))

Hvordan visse RDBMS håndterer ting er ikke altid en nyttig indikator for korrekt adfærd. Postgres-manualen antyder dette:

Det betyder, at selv i tilstedeværelsen af ​​en unik begrænsning er det muligt at gemme duplikerede rækker, der indeholder en nulværdi i mindst én af de begrænsede kolonner. Denne adfærd er i overensstemmelse med SQL-standarden, men vi har hørt, at andre SQL-databaser muligvis ikke følger denne regel .Så vær forsigtig, når du udvikler applikationer, der er beregnet til at være bærbare.

Fed fremhævelse mine.




  1. Regneark vs. databaser:Er det tid til at skifte? Del 2

  2. Returnere en forespørgsel fra en funktion?

  3. Indsæt Update lagret proc på SQL Server

  4. LIMIT søgeord på MySQL med forberedt erklæring