Pokud potřebujete chcete-li povolit hodnoty NULL, použijte UNIQUE
omezení namísto PRIMARY KEY
(a přidejte náhradní sloupec PK, navrhuji serial
). To umožňuje, aby sloupce byly NULL:
CREATE TABLE distributor (
distributor_id serial PRIMARY KEY
, m_id integer
, x_id integer
, UNIQUE(m_id, x_id)
);
Poznámka , nicméně (podle dokumentace):
Pro účely jedinečného omezení nejsou hodnoty null považovány za rovné.
Ve vašem případě můžete zadat něco jako (1, NULL)
pro (m_id, x_id)
kolikrát, aniž by došlo k porušení omezení. Postgres nikdy nepovažuje dvě hodnoty NULL za rovné - podle definice ve standardu SQL.
Pokud potřebujete ošetřit NULL
hodnoty jako rovné zakázat takové "duplikáty", vidím dvě možnosti :
1. Dva dílčí indexy
Navíc na UNIQUE
omezení výše:
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;
Ale to se rychle vymkne z rukou s více než dvěma sloupci, které mohou mít hodnotu NULL. Viz:
- Vytvořte jedinečné omezení s prázdnými sloupci
2. UNIQUE
s více sloupci index na výrazech
Místo omezení UNIQUE. Potřebujeme volnou výchozí hodnotu, která se nikdy nevyskytuje v příslušných sloupcích, například -1
. Přidejte CHECK
omezení zakázat to:
CREATE TABLE distributor (
distributor serial PRIMARY KEY
, m_id integer
, x_id integer
, CHECK (m_id <> -1)
, CHECK (x_id <> -1)
);
CREATE UNIQUE INDEX distributor_uni_idx ON distributor (COALESCE(m_id, -1)
, COALESCE(x_id, -1))
Jak určité RDBMS řeší věci není vždy užitečným ukazatelem správného chování. Manuál Postgres naráží na toto:
To znamená, že i v případě jedinečného omezení je možné ukládat duplicitní řádky, které obsahují nulovou hodnotu alespoň v jednom z omezených sloupců. Toto chování odpovídá standardu SQL, ale slyšeli jsme, že jiné databáze SQL toto pravidlo nemusí dodržovat .Buďte opatrní při vývoji aplikací, které mají být přenosné.
Tučné zdůraznění moje.