L'uso di più vincoli univoci su una singola tabella è considerato design errato?


8

Stavo osservando la INSERT INTO .. ON CONFLICT (..) DO UPDATE ..sintassi di PostgreSQL e ho realizzato che non è possibile eseguire più controlli univoci dei vincoli con esso. Voglio dire, o fai riferimento a un indice univoco composito dai nomi delle colonne ON CONFLICT (Name, Symbol)(se l'indice univoco è definito per queste due colonne) o usi la chiave primaria. Se si definiscono due indici univoci separati per le colonne, è possibile verificarne solo 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';

Potrebbe generare un errore, dicendo che Jè un duplicato. Tuttavia, questo esempio è semplicemente un cattivo design, perché il simbolo dovrebbe essere in un'altra tabella ed essere collegato alla tabella degli studenti tramite una relazione uno-a-molti. È per questo che mi chiedo, forse PostgreSQL è on conflictstato progettato in questo modo, perché puoi SEMPRE ristrutturare le tabelle in un modo, dove esiste un solo indice univoco. È vero o c'è un'altra ragione?

Esempio di violino: http://www.sqlfiddle.com/#!17/9c0ce


puoi SEMPRE ristrutturare le tabelle in un modo, dove esiste un solo indice univoco Ci sono EntityA ed EntityB. Ci sono 2 istanze di ciascuno. Qualsiasi istanza EntityA può combinarsi con qualsiasi istanza EntityB, quindi ci sono 2 possibili combinazioni in cui vengono utilizzate tutte le istanze. Una di queste combinazioni è realizzata e devi memorizzarla. Ora prova a creare uno schema in cui non esiste una tabella con 2 uniques con tutti i vincoli che impediscono i dati illegali.
Akina,

@Akina Ho perso il tuo punto. Se due entità sono collegate tramite una relazione da molte a molte, si crea una tabella di collegamenti, memorizzando le loro chiavi esterne, quindi non esiste una tabella con 2 indici univoci.
appl3r,

Un'istanza può essere utilizzata una sola volta, quindi è necessario disporre di 2 indici uniqie in una tabella collegata (da ciascuna entità separatamente) per impedire l'uso dell'istanza già utilizzata.
Akina,

Anche se è vero, questo è un problema: guarda l'esempio nella risposta di Michael Green. Dividere una tabella così semplice in 4 tabelle è sicuramente un mal di testa, pensato dal momento che è una semplice dizione, non è come se dovessi aver bisogno dell'opzione "ON CONFLICT".
Walfrat,

Risposte:


8

C'è sempre la sesta, o chiave di dominio, forma normale. Qui ogni colonna non chiave diventa la propria tabella. Quindi la tabella 3NF T (Key, Col1, Col2, ..) diventa T1 (Key, Col1), T2 (Key, Col2) ecc. Queste nuove tabelle che richiedono unicità possono essere dichiarate.

Penso che avere più vincoli univoci su una tabella sia perfettamente OK, tuttavia. Prendi ad esempio una tabella di paesi. Ciò avrebbe, per esempio, un ID, il nome, il codice ISO, la capitale e alcuni altri. Ognuno di questi primi quattro sarà unico. Inoltre, se vogliamo che il nostro sistema faccia affidamento sul fatto che ognuno di essi sia unico, credo che dovremmo definire vincoli univoci per ciascuno di essi. Ciò applica le verità sui dati su cui tutti i consumatori possono fare affidamento.


Pensi che il design postgresql sia solo il risultato di miopia allora? Oracle, SQL Server, DB2 e altri forniscono tutti un modo per tenere conto di tutte le chiavi univoche in tale situazione (usando l' MERGEistruzione). Il pg è ON CONFLICT DO UPDATE stato aggiunto solo in 9.5 ed è molto più limitato.
appl3r,

1
@ appl3r è solo un dettaglio di implementazione. Puoi fare a ON CONFLICT DO NOTHINGmeno di menzionare vincoli unici e li considererà tutti (e non farà nulla). Quando vuoi fare ON CONFLICT DO UPDATE, devi dichiarare una colonna o un vincolo e solo uno. La restrizione potrebbe essere revocata nelle versioni future.
ypercubeᵀᴹ

Sono un po 'confuso dal tuo primo paragrafo. Diciamo che abbiamo diviso la tabella Student (ID, Nome, Simbolo) dell'OP in S1 (Id, Nome) e S2 (Id, Simbolo) per provare a trasformarla in DK / NF. Quali sarebbero i vincoli (di dominio e) chiave su S2 e come garantirebbero che ogni studente abbia sia un singolo ID unico che un singolo simbolo unico?
Ilmari Karonen,

1
La domanda era (tipo di) "Se vanno bene più indici UNIQUE, perché PostgreSQL richiede che sia specificato un indice arbitro ON CONFLICT ... DO UPDATEe sfortunatamente questa risposta non risponde a quel punto.
AndreKR,

@AndreKR si rivolge al (grassetto): "è stato (questa funzione di Postgres) progettato in questo modo, perché puoi SEMPRE ristrutturare le tabelle in un modo, dove esiste un solo indice univoco?" Puoi sicuramente aggiungere un'altra risposta, affrontando il punto che menzioni
ypercubeᵀᴹ
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.