it-swarm-eu.dev

PostgreSQL - insert / update porušuje omezení cizího klíče

Jsem nový v postgreSQL. Mám 3 tabulky, jedna tabulka odkazuje na primární klíče druhé 2 tabulky. Ale nemohl jsem vložit data do Table3. Viz níže uvedený kód:

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

CHYBA: vložit nebo aktualizovat v tabulce "Tabulka 3" porušuje omezení cizího klíče "Table3_DataID_fkey" DETAIL: Klíč (DataID) = (27856) není v tabulce "Tabulka1".

Když jsem se pokusil vložit data do 3 tabulek, došlo k chybě. Odkázal jsem postgreSQL dokumentace a změnil jsem kód následovně: (Bohužel to ukázalo další chybu)

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

CHYBA: není povoleno více primárních klíčů pro tabulku „Tabulka 3“ Řádek 65: PRIMÁRNÍ KLÁVES („ID_ID“, „Adresa“)

Prosím, pomozte mi ... Jak mohu vytvořit odkaz?

Změnil jsem ID jako UNIQUE a odstranil řádek PRIMARY KEY ("ID"). V té době ukazuje další chybu, jako například:

CHYBA: duplicitní hodnota klíče porušuje jedinečné omezení "Table3_pkey"

11
Haseena

S tabulkami je několik problémů. Pokusím se nejprve oslovit cizí klíče, protože jste se na ně zeptali :)

Ale předtím bychom si měli uvědomit, že dvě sady tabulek (první tři, které jste vytvořili a druhou sadu, kterou jste vytvořili po vynechání první sady) jsou stejné. Definice Table3 Ve vašem druhém pokusu má samozřejmě syntaktické a logické chyby, ale základní myšlenka je:

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

Tato definice říká PostgreSQL zhruba takto: „Vytvořte tabulku se čtyřmi sloupci, jeden bude primární klíč (PK), ostatní mohou být NULL. Pokud je vložen nový řádek, zaškrtněte DataID a Address: pokud obsahují jinou hodnotu než NULL (řekněme 27856), pak zkontrolujte Table1 pro DataID˙ a Table2 pro Address. Pokud v těchto tabulkách taková hodnota neexistuje, vraťte chybu. " Tento poslední bod, který jste viděli jako první:

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

Tak jednoduché: pokud v řádku Table1 Není žádný řádek, kde DataID = 27856, Pak tento řádek nelze vložit do Table3.

Pokud tento řádek potřebujete, měli byste první vložit řádek do Table1 Pomocí DataID = 27856 A teprve poté zkusit vložit do Table3. Pokud se vám zdá, že ne, co chcete, popište v několika větách, čeho chcete dosáhnout a my vám můžeme pomoci s dobrým designem.


A teď o dalších problémech.

Vaše PK definujete jako

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

Primární klíč znamená, že všechny položky v něm se od sebe liší, to znamená, že hodnoty jsou UNIQUE. Pokud do sloupce DEFAULT zadáte statický UNIQUE (jako '0'), Budete mít vždy špatná překvapení. To je to, co jste dostali ve své třetí chybové zprávě.

Kromě toho '0' Znamená textový řetězec, ale ne číslo (ve vašem případě bigint nebo numeric). Místo toho použijte jednoduše 0 (Nebo jej nepoužívejte vůbec, jak jsem psal výše).

A poslední bod (možná se mýlím): v Table2 Je vaše pole Address nastaveno na numeric(20). Zároveň je to PK tabulky. Název sloupce a typ dat naznačují, že se tato adresa může v budoucnu změnit. Pokud je to pravda, je to pro PK velmi špatná volba. Přemýšlejte o následujícím scénáři: máte adresu '1234567890454', která má dítě jako Table3 Jako

ID        DataID           Address             Data
123       3216547          1234567890454       654897564134569

Nyní se tato adresa změní na něco jiného. Jak si přinutíte, aby vaše dítě řádek Table3 Následovalo jeho rodiče na novou adresu? (Existují řešení, ale může to způsobit mnoho nejasností.) Pokud je to váš případ, přidejte do tabulky sloupec ID, který nebude obsahovat žádné informace ze skutečného světa, bude to jednoduše sloužit jako identifikační hodnota (to je , ID) pro adresu.

16
dezso

Vše záleží na tom, co chcete s daty dělat.

První příklad - chcete mít konzistentní data ve všech tabulkách, ale zkuste vložit hodnoty, které neodpovídají tabulce1.

Druhý příklad - nechcete mít konzistentní data, ale zkuste udělat něco jiného, ​​ne přesně vědět, co. Tabulka nemůže mít více než jeden primární klíč.

Třetí příklad - stále nevíte, čeho chcete dosáhnout, a na sloupec, který může mít stejnou hodnotu vícekrát, umístíte omezení UNIQUE.

Pokud chcete pouze vložit data, zbavte se odkazů na cizí klíč v prvním příkladu. Pokud chcete mít konzistentní data ve všech tabulkách - proveďte vyčištění dat a poté je vložte do tabulek s omezeními cizího klíče.

tl; dr: vložit vaše data do Table3 s kódem z prvního příkladu - vložit chybějící hodnoty do sloupce Table1.DataID, které existují v Table3.DataId.

0
BartekR