PostgreSQL: l'inserimento / aggiornamento viola i vincoli della chiave esterna


12

Sono nuovo in postgreSQL. Ho 3 tabelle, una tabella fa riferimento alle chiavi primarie dell'altra 2 tabella. Ma non sono riuscito a inserire dati nel file Table3. Vedi il codice qui sotto:

DROP TABLE Table1 CASCADE;
CREATE TABLE Table1(
  "DataID" bigint NOT NULL DEFAULT '0',
  "AdData" integer DEFAULT NULL,
  PRIMARY KEY ("DataID")
);

DROP TABLE IF EXISTS Table2 CASCADE;
CREATE TABLE Table2 (
  "Address" numeric(20) NOT NULL DEFAULT '0',
  "Value" numeric(20) DEFAULT NULL,
  PRIMARY KEY ("Address")
);

DROP TABLE IF EXISTS Table3 CASCADE; 
CREATE TABLE table3 (   
  "ID" bigint NOT NULL DEFAULT '0',   
  "DataID" bigint DEFAULT NULL,   
  "Address" numeric(20) DEFAULT NULL,   
  "Data" bigint DEFAULT NULL,
   PRIMARY KEY ("ID"),   
   FOREIGN KEY ("DataID") REFERENCES Table1("DataID") on delete cascade on update cascade,   
   FOREIGN KEY ("Address") REFERENCES Table2("Address") on delete cascade on update cascade
);

ERRORE: inserire o aggiornare nella tabella "Tabella 3" viola il vincolo di chiave esterna "Tabella 3_DataID_fkey" DETTAGLIO: Chiave (DataID) = (27856) non è presente nella tabella "Tabella1".

Quando ho provato a inserire i dati nelle 3 tabelle, si è verificato un errore. Ho fatto riferimento alla documentazione di postgreSQL e ho modificato il mio codice come segue: (Purtroppo ha mostrato un altro errore)

DROP TABLE Table1 CASCADE;
CREATE TABLE Table1(
  "DataID" bigint NOT NULL DEFAULT '0',
  "AdData" integer DEFAULT NULL,
  PRIMARY KEY ("DataID")
);

DROP TABLE IF EXISTS Table2 CASCADE;
CREATE TABLE Table2 (
  "Address" numeric(20) NOT NULL DEFAULT '0',
  "Value" numeric(20) DEFAULT NULL,
  PRIMARY KEY ("Address")
);

DROP TABLE IF EXISTS Table3 CASCADE; 
CREATE TABLE table3 (   
  "ID" bigint NOT NULL DEFAULT '0',   
  "DataID" bigint DEFAULT NULL REFERENCES Table1 ON DELETE RESTRICT,
  "Address" numeric(20) DEFAULT NULL REFERENCES Table2 ON DELETE CASCADE, 
  "Data" bigint DEFAULT NULL,
   PRIMARY KEY ("ID"),   
   PRIMARY KEY("DataID", "Address")
);

ERRORE: non sono consentite più chiavi primarie per la tabella "Tabella3" LINEA 65: PRIMARY KEY ("DataID", "Indirizzo")

Aiutatemi ... Come posso creare il riferimento?

Ho cambiato l' IDas UNIQUEe rimosso la linea PRIMARY KEY ("ID"). A quel tempo mostra un altro errore come:

ERRORE: il valore della chiave duplicata viola il vincolo univoco "Table3_pkey"

Risposte:


17

Ci sono alcuni problemi con i tuoi tavoli. Cercherò di indirizzare prima le chiavi esterne, dal momento che hai una domanda su di loro :)

Ma prima, dovremmo renderci conto che i due set di tabelle (i primi tre che hai creato e il secondo set, che hai creato dopo aver lasciato cadere il primo set) sono gli stessi. Naturalmente, la definizione di Table3nel tuo secondo tentativo ha sintassi ed errori logici, ma l'idea di base è:

CREATE TABLE table3 (   
  "ID" bigint NOT NULL DEFAULT '0',   
  "DataID" bigint DEFAULT NULL,   
  "Address" numeric(20) DEFAULT NULL,   
  "Data" bigint DEFAULT NULL,
   PRIMARY KEY ("ID"),   
   FOREIGN KEY ("DataID") REFERENCES Table1("DataID") on delete cascade on update cascade,   
   FOREIGN KEY ("Address") REFERENCES Table2("Address") on delete cascade on update cascade
);

Questa definizione dice a PostgreSQL approssimativamente quanto segue: "Crea una tabella con quattro colonne, una sarà la chiave primaria (PK), le altre possono essere NULL. Se viene inserita una nuova riga, controlla DataIDe Address: se contengono un valore non NULL ( dì 27856), quindi Table1cerca DataID˙ e Table2per Address. Se non esiste un valore simile in quelle tabelle, restituisci un errore. " Quest'ultimo punto che hai visto per primo:

ERROR: insert or update on table "Table3" violates foreign key constraint 
    "Table3_DataID_fkey" DETAIL: Key (DataID)=(27856) is not present in table "Table1".

Così semplice: se non ci sono righe in Table1cui DataID = 27856, non è possibile inserire quella riga in Table3.

Se hai bisogno di quella riga, devi prima inserire una riga in Table1con DataID = 27856, e solo allora provare a inserire in Table3. Se questo non ti sembra ciò che desideri, descrivi in ​​poche frasi ciò che vuoi ottenere e possiamo aiutarti con un buon design.


E ora sugli altri problemi.

Definisci i tuoi PK come

CREATE all_your_tables (
    first_column NOT NULL DEFAULT '0',   
    [...]
    PRIMARY KEY ("ID"),  

Una chiave primaria significa che tutti gli elementi in essa contenuti sono diversi l'uno dall'altro, ovvero i valori lo sono UNIQUE. Se dai una statica DEFAULT(come '0') a una UNIQUEcolonna, sperimenterai sempre brutte sorprese. Questo è ciò che hai nel tuo terzo messaggio di errore.

Inoltre, '0'significa una stringa di testo, ma non un numero ( biginto numericnel tuo caso). Usa semplicemente 0invece (o non usarlo affatto, come ho scritto sopra).

E un ultimo punto (potrei sbagliarmi qui): in Table2, il tuo Addresscampo è impostato su numeric(20). Allo stesso tempo, è il PK della tabella. Il nome della colonna e il tipo di dati suggeriscono che questo indirizzo può cambiare in futuro. Se questo è vero, allora è una pessima scelta per un PK. Pensa al seguente scenario: hai un indirizzo "1234567890454", che ha un figlio Table3simile

ID        DataID           Address             Data
123       3216547          1234567890454       654897564134569

Ora quell'indirizzo sembra cambiare in qualcos'altro. In che modo fai in modo che tuo figlio remi Table3seguendo il suo genitore al nuovo indirizzo? (Ci sono soluzioni per questo, ma possono causare molta confusione.) Se questo è il tuo caso, aggiungi una colonna ID alla tua tabella, che non conterrà alcuna informazione dal mondo reale, servirà semplicemente come valore identificativo (ovvero , ID) per un indirizzo.


Grazie per il tuo prezioso suggerimento. Proverò a progettare meglio in base ai tuoi suggerimenti. Ora il primo errore è stato risolto.
Haseena,

0

Tutto dipende da cosa vuoi fare con i dati.

Primo esempio: vuoi avere dati coerenti in tutte le tabelle, ma provi a inserire valori che non corrispondono a Tabella1.

Secondo esempio: non vuoi avere dati coerenti, ma prova a fare qualcos'altro, non sai esattamente cosa. La tabella non può avere più di una chiave primaria.

Terzo esempio: non sai ancora cosa vuoi ottenere e metti un vincolo UNICO sulla colonna che può avere lo stesso valore più volte.

Se vuoi solo inserire i tuoi dati, elimina i riferimenti a chiave esterna nel primo esempio. Se si desidera disporre di dati coerenti in tutte le tabelle, eseguire la pulizia dei dati e quindi inserire nelle tabelle CON vincoli di chiave esterna.

tl; dr: per inserire i tuoi dati in Table3 con il codice del primo esempio - inserisci i valori mancanti nella colonna Table1.DataID presenti in Table3.DataId.

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.