PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Съставният ПЪРВИЧЕН КЛЮЧ налага ограничения NOT NULL върху участващите колони

Ако трябва за да разрешите NULL стойности, използвайте UNIQUE ограничение вместо PRIMARY KEY (и добавете заместваща PK колона, предлагам serial ). Това позволява колоните да бъдат NULL:

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

Забележка , обаче (по документация):

За целите на уникално ограничение нулевите стойности не се считат за равни.

Във вашия случай можете да въведете нещо като (1, NULL) за (m_id, x_id) произволен брой пъти, без да се нарушава ограничението. Postgres никога не счита две NULL стойности равни - според дефиницията в стандарта SQL.

Ако трябва да третирате NULL стойности като равни за забрана на такива "дубликати", виждам две опции :

1. Два частични индекса

В допълнение към UNIQUE ограничение по-горе:

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;

Но това бързо излиза извън ръцете с повече от две колони, които могат да бъдат NULL. Вижте:

  • Създайте уникално ограничение с нулеви колони

2. UNIQUE с няколко колони индекс на изрази

Вместо ограничението UNIQUE. Нуждаем се от безплатна стойност по подразбиране, която никога не присъства в участващите колони, като -1 . Добавете CHECK ограничения, за да го забраните:

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))

Как определени RDBMS се справят с нещата не винаги е полезен индикатор за правилно поведение. Ръководството на Postgres намеква за това:

Това означава, че дори при наличието на уникално ограничение е възможно да се съхраняват дублиращи се редове, които съдържат нулева стойност в поне една от ограничените колони. Това поведение отговаря на стандарта SQL, но чухме, че други SQL бази данни може да не следват това правило .Така че бъдете внимателни, когато разработвате приложения, които са предназначени да бъдат преносими.

Удебелен акцент мой.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Конвертирайте django RawQuerySet в Queryset

  2. SQL:Когато става въпрос за НЕ В и НЕ РАВНО НА, кое е по-ефективно и защо?

  3. Проблем при извличане на записи с празен масив

  4. Справяне с бавни заявки с PostgreSQL

  5. Конкатениране на множество редове в масив с SQL на PostgreSQL