sql >> Base de Datos >  >> RDS >> PostgreSQL

La CLAVE PRINCIPAL compuesta impone restricciones NOT NULL en las columnas involucradas

Si necesitas para permitir valores NULL, use un UNIQUE restricción en lugar de una PRIMARY KEY (y agregue una columna PK sustituta, sugiero un serial ). Esto permite que las columnas sean NULL:

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

Nota , sin embargo (por documentación):

A los efectos de una restricción única, los valores nulos no se consideran iguales.

En su caso, podría ingresar algo como (1, NULL) para (m_id, x_id) cualquier número de veces sin violar la restricción. Postgres nunca considera dos valores NULL iguales - según definición en el estándar SQL.

Si necesita tratar NULL valores como iguales para no permitir tales "duplicados", veo dos opciones :

1. Dos índices parciales

Además al UNIQUE restricción anterior:

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;

Pero esto se sale de control rápidamente con más de dos columnas que pueden ser NULL. Ver:

  • Crear restricción única con columnas nulas

2. Un UNIQUE de varias columnas índice de expresiones

En lugar de la restricción ÚNICA. Necesitamos un valor predeterminado gratuito que nunca esté presente en las columnas involucradas, como -1 . Añadir CHECK restricciones para no permitirlo:

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

Cómo ciertos RDBMS manejan las cosas no siempre es un indicador útil para el comportamiento adecuado. El manual de Postgres sugiere esto:

Eso significa que incluso en presencia de una restricción única, es posible almacenar filas duplicadas que contengan un valor nulo en al menos una de las columnas restringidas. Este comportamiento se ajusta al estándar SQL, pero hemos escuchado que otras bases de datos SQL podrían no seguir esta regla .Así que tenga cuidado al desarrollar aplicaciones destinadas a ser portátiles.

Énfasis en negrita mío.