sql >> Databáze >  >> RDS >> PostgreSQL

Složený PRIMARY KEY vynucuje omezení NOT NULL na příslušné sloupce

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 &lt> -1)
 , CHECK (x_id &lt> -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.




  1. Ekvivalent explode() pro práci s řetězci v MySQL

  2. 4 Úžasné zdroje monitorování SQL Serveru pro správce databází

  3. Použití parametru jako názvu sloupce ve funkci Postgres

  4. MySQL:Nelze vytvořit tabulku (errno:150)