PostgreSQL - Einfügen / Aktualisieren verletzt Fremdschlüsseleinschränkungen

11

Ich bin neu in postgreSQL. Ich habe 3 Tabellen, eine Tabelle verweist auf die Primärschlüssel der anderen 2 Tabelle. Aber ich konnte keine Daten in die einfügen Table3. Siehe den folgenden Code:

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

FEHLER: Einfügen oder Aktualisieren in Tabelle "Tabelle3" verstößt gegen die Fremdschlüsseleinschränkung "Table3_DataID_fkey". DETAIL: Schlüssel (DataID) = (27856) ist in Tabelle "Tabelle1" nicht vorhanden.

Beim Versuch, Daten in die 3 Tabellen einzufügen, ist ein Fehler aufgetreten. Ich habe auf die postgreSQL-Dokumentation verwiesen und meinen Code wie folgt geändert: (Leider wurde ein weiterer Fehler angezeigt. )

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

FEHLER: Mehrere Primärschlüssel für Tabelle "Tabelle3" sind nicht zulässig. LINE 65: PRIMARY KEY ("DataID", "Address")

Bitte helfen Sie mir ... Wie kann ich die Referenz erstellen?

Ich habe das IDas geändert UNIQUEund die Zeile entfernt PRIMARY KEY ("ID"). Zu diesem Zeitpunkt zeigt es einen weiteren Fehler wie:

FEHLER: Doppelter Schlüsselwert verletzt eindeutige Einschränkung "Table3_pkey"

Haseena
quelle

Antworten:

16

Es gibt einige Probleme mit Ihren Tabellen. Ich werde versuchen, zuerst die Fremdschlüssel zu adressieren, da Sie Fragen dazu gestellt haben :)

Zuvor sollten wir jedoch feststellen, dass die beiden Tabellensätze (die ersten drei, die Sie erstellt haben, und der zweite Satz, den Sie nach dem Löschen des ersten Satzes erstellt haben) identisch sind. Natürlich hat die Definition Table3in Ihrem zweiten Versuch Syntax und logische Fehler, aber die Grundidee ist:

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

Diese Definition sagt PostgreSQL ungefähr Folgendes: "Erstellen Sie eine Tabelle mit vier Spalten, eine ist der Primärschlüssel (PK), die anderen können es sein NULL. Wenn eine neue Zeile eingefügt wird, überprüfen Sie DataIDund Address: wenn sie einen Nicht-NULL-Wert enthalten ( sagen wir 27856), dann suchen Sie Table1nach DataID˙und Table2nach Address. Wenn diese Tabellen keinen solchen Wert enthalten, geben Sie einen Fehler zurück. " Dieser letzte Punkt, den Sie zuerst gesehen haben:

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

So einfach: Wenn es keine Zeile in Table1wo gibt DataID = 27856, können Sie diese Zeile nicht einfügen Table3.

Wenn Sie diese Zeile benötigen, sollten Sie zuerst eine Zeile in Table1mit einfügen DataID = 27856und erst dann versuchen, in einzufügen Table3. Wenn Ihnen dies nicht so erscheint, wie Sie es möchten, beschreiben Sie bitte in wenigen Sätzen, was Sie erreichen möchten, und wir können Ihnen bei einem guten Design helfen.


Und nun zu den anderen Problemen.

Sie definieren Ihre PKs als

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

Ein Primärschlüssel bedeutet, dass sich alle darin enthaltenen Elemente voneinander unterscheiden, dh die Werte sind UNIQUE. Wenn Sie einer Spalte ein statisches DEFAULT( Gefällt mir) geben , werden Sie die ganze Zeit über böse Überraschungen erleben. Dies haben Sie in Ihrer dritten Fehlermeldung erhalten.'0'UNIQUE

Außerdem '0'bedeutet dies eine Textzeichenfolge, jedoch keine Zahl ( bigintoder numericin Ihrem Fall). Verwenden Sie 0stattdessen einfach (oder verwenden Sie es überhaupt nicht, wie ich oben geschrieben habe).

Und noch ein letzter Punkt (ich kann mich hier irren): In Table2, Ihr AddressFeld ist auf eingestellt numeric(20). Gleichzeitig ist es die PK der Tabelle. Der Spaltenname und der Datentyp deuten darauf hin, dass sich diese Adresse in Zukunft ändern kann. Wenn dies zutrifft, ist es eine sehr schlechte Wahl für eine PK. Stellen Sie sich das folgende Szenario vor: Sie haben eine Adresse '1234567890454', die ein Kind in Table3like hat

ID        DataID           Address             Data
123       3216547          1234567890454       654897564134569

Jetzt ändert sich diese Adresse zu etwas anderem. Wie bringen Sie Ihr Kind dazu Table3, seinem Elternteil zur neuen Adresse zu folgen? (Es gibt Lösungen dafür, die jedoch viel Verwirrung stiften können.) Wenn dies der Fall ist, fügen Sie Ihrer Tabelle eine ID-Spalte hinzu, die keine Informationen aus der realen Welt enthält. Sie dient lediglich als Identifikationswert (d. H.) , ID) für eine Adresse.

dezso
quelle
Vielen Dank für Ihren wertvollen Vorschlag. Ich werde versuchen, auf der Grundlage Ihrer Vorschläge ein besseres Design zu erzielen. Jetzt ist der erste Fehler behoben.
Haseena
0

Es hängt alles davon ab, was Sie mit den Daten machen möchten.

Erstes Beispiel: Sie möchten konsistente Daten in allen Tabellen haben, versuchen jedoch, Werte einzufügen, die nicht mit Tabelle1 übereinstimmen.

Zweites Beispiel: Sie möchten keine konsistenten Daten haben, aber versuchen, etwas anderes zu tun, ohne genau zu wissen, was. Tabelle kann nicht mehr als einen Primärschlüssel haben.

Drittes Beispiel: Sie wissen immer noch nicht, was Sie erreichen möchten, und setzen eine EINZIGARTIGE Einschränkung auf eine Spalte, die möglicherweise mehrmals denselben Wert hat.

Wenn Sie nur Ihre Daten einfügen möchten, entfernen Sie im ersten Beispiel Fremdschlüsselreferenzen. Wenn Sie konsistente Daten in allen Tabellen haben möchten, führen Sie die Datenbereinigung durch und fügen Sie sie dann in Tabellen mit Fremdschlüsseleinschränkungen ein.

tl; dr: Um Ihre Daten mit Code aus dem ersten Beispiel in Tabelle 3 einzufügen, fügen Sie fehlende Werte in die Spalte Table1.DataID ein, die in Table3.DataId vorhanden ist.

BartekR
quelle