¿Usar múltiples restricciones únicas en una sola tabla se considera un mal diseño?

8

Estaba mirando la INSERT INTO .. ON CONFLICT (..) DO UPDATE ..sintaxis de PostgreSQL y me di cuenta de que no puede hacer múltiples comprobaciones de restricciones únicas con ella. Quiero decir, o se refiere a un índice único compuesto por los nombres de las columnas ON CONFLICT (Name, Symbol)(si el índice único está definido para estas dos columnas), o usa la clave primaria. Si define dos índices únicos separados para las columnas, solo puede verificar uno.

CREATE TABLE student
    (Id int primary key, Name varchar(50), Symbol varchar(50),
      CONSTRAINT col1_unique UNIQUE (Name),
      CONSTRAINT col2_unique UNIQUE (Symbol)
    ); 

INSERT INTO student
    (Id, Name, Symbol)
VALUES
    (1, 'John', 'J'),
    (2, 'David', 'D'),
    (3, 'Will', 'W');

INSERT INTO student
    (Id, Name, Symbol)
VALUES
    (4, 'Jeremy', 'J')
   on conflict(Name) DO UPDATE
   set Name = 'Jeremy';

Podría arrojar un error, diciendo que Jes un duplicado. Sin embargo, este ejemplo es simplemente un mal diseño, porque el Símbolo debe estar en otra mesa y estar conectado a la mesa del alumno a través de una relación de uno a muchos. Es por eso que me pregunto, tal vez PostgreSQL on conflictfue diseñado de esta manera, porque SIEMPRE puede reestructurar las tablas de una manera, donde solo hay un único índice único. ¿Es cierto o hay otra razón?

Violín de ejemplo: http://www.sqlfiddle.com/#!17/9c0ce

appl3r
fuente
SIEMPRE puede reestructurar las tablas de una manera, donde solo hay un único índice único Hay EntityA y EntityB. Hay 2 instancias de cada uno. Cualquier instancia de EntityA puede combinarse con cualquier instancia de EntityB, por lo que hay 2 combinaciones posibles donde se utilizan todas las instancias. Se realiza una de estas combinaciones y debe almacenarla. Ahora intente hacer un esquema donde no exista una tabla con 2 exclusivos con todas las restricciones que evite datos ilegales.
Akina
@ Akina, perdí tu punto. Si dos entidades están conectadas a través de una relación de muchos a muchos, crea una tabla de enlaces, almacenando sus claves foráneas, por lo que no hay una tabla con 2 índices únicos.
appl3r
Una instancia se puede usar solo una vez, por lo que debe tener 2 índices únicos en una tabla vinculada (por cada entidad por separado) para evitar el uso de la instancia ya utilizada.
Akina
Si bien eso es cierto, eso es bastante molesto: vea la muestra en la respuesta de Michael Green. Dividir una tabla tan simple en 4 tablas es definitivamente un dolor de cabeza, ya que es un diccionario simple, no es como si necesitaras la opción "EN CONFLICTO".
Walfrat

Respuestas:

8

Siempre hay sexta, o clave de dominio, forma normal. Aquí cada columna sin clave se convierte en su propia tabla. Por lo tanto, la tabla 3NF T (Clave, Col1, Col2, ..) se convierte en T1 (Clave, Col1), T2 (Clave, Col2), etc. Las tablas nuevas que requieren unicidad pueden hacer que se declare.

Sin embargo, creo que tener múltiples restricciones únicas en una tabla está perfectamente bien. Tomemos por ejemplo una tabla de países. Esto tendría, por ejemplo, una identificación, el nombre, el código ISO, la ciudad capital y algunos otros. Cada uno de esos primeros cuatro será único. Además, si queremos que nuestro sistema se base en que cada uno sea único, creo que deberíamos definir restricciones únicas para cada uno. Esto impone verdades sobre los datos en los que pueden confiar todos los consumidores.

Michael Green
fuente
¿Crees que el diseño postgresql es solo el resultado de la miopía entonces? Oracle, SQL Server, DB2 y otros proporcionan una forma de tener en cuenta todas las claves únicas en tal situación (utilizando la MERGEdeclaración). El pg ON CONFLICT DO UPDATE solo se agregó en 9.5 y es mucho más limitado.
appl3r el
1
@ appl3r es solo un detalle de implementación. Puede hacerlo ON CONFLICT DO NOTHINGsin mencionar restricciones únicas y las considerará todas (y no hará nada). Cuando quiera hacerlo ON CONFLICT DO UPDATE, debe declarar una columna o una restricción y solo una. La restricción podría ser levantada en futuras versiones.
ypercubeᵀᴹ
Estoy un poco confundido por tu primer párrafo. Digamos que dividimos la tabla Estudiante (Id, Nombre, Símbolo) del OP en S1 (Id, Nombre) y S2 (Id, Símbolo) para intentar convertirlo en DK / NF. ¿Cuáles serían las restricciones de (dominio y) clave en S2, y cómo garantizarían que cada alumno tenga un Id único y un Símbolo único?
Ilmari Karonen
1
La pregunta era (tipo de) "Si hay varios índices UNIQUE están bien, ¿por qué PostgreSQL requiere que un índice de árbitro se especifica para ON CONFLICT ... DO UPDATEy por desgracia, esta respuesta no aborda ese punto.
AndreKR
@AndreKR aborda el (en negrita): "¿fue (esta característica de Postgres) diseñada de esta manera, porque SIEMPRE puede reestructurar las tablas de una manera, donde solo hay un único índice único?" Ciertamente puede agregar otra respuesta, abordando el punto que menciona
ypercubeᵀᴹ