it-swarm-eu.dev

Jak používat RESTRICT pro cizí klíč v mysql?

Ve struktuře databáze

  CREATE TABLE Country (
  name varchar(40) NOT NULL,
  PRIMARY KEY  (name)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

CREATE TABLE City (
  name varchar(40) NOT NULL,
  PRIMARY KEY  (name)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

CREATE TABLE Map (
  country varchar(40) NOT NULL,
  city varchar(100) NOT NULL,
  PRIMARY KEY  (country,city),
  FOREIGN KEY (country) REFERENCES Country (name) ON DELETE CASCADE,
  FOREIGN KEY (city) REFERENCES City (name) ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Očekávám, že odstraním rodiče z City tím, že ponechám odpovídající hodnotu v dítěti neporušenou těmito třemi stejnými příkazy

  FOREIGN KEY (city) REFERENCES City (name) ON DELETE NO ACTION
  FOREIGN KEY (city) REFERENCES City (name) ON DELETE RESTRICT
  FOREIGN KEY (city) REFERENCES City (name)

Ale při použití NO ACTION OR RESTRICT nebo vynechání ON DELETE. MySQL mi nedovoluje odstranit tuto chybu z nadřazeného sloupce s touto chybou:

ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails 
('test'.'Map', CONSTRAINT 'Map_ibfk_2' FOREIGN KEY ('city') REFERENCES 'City'('name')
 ON DELETE RESTRICT

Kde se mýlím? Není odpovědností NO ACTION SQL odstranit rodiče a opustit dětského sirotka?

11
Googlebot

Podle Dokumentace MySQL na DELETE RESTRICT

• RESTRICT: Odmítne operaci odstranění nebo aktualizace nadřazené tabulky. Zadání RESTRICT (nebo NO ACTION) je stejné jako vynechání klauzule ON DELETE nebo ON UPDATE.

Pokud jde o ŽÁDNÁ AKCE

• ŽÁDNÁ AKCE: Klíčové slovo ze standardního SQL. V MySQL, ekvivalentní s RESTRICT. InnoDB odmítne operaci smazání nebo aktualizace nadřazené tabulky, pokud je v referenční tabulce související hodnota cizího klíče. Některé databázové systémy mají odložené kontroly a žádná akce je odložená kontrola. V MySQL jsou omezení cizího klíče zkontrolována okamžitě, takže ŽÁDNÁ AKCE není stejná jako RESTRICT.

DELETE RESTRICT chrání rodiče před odstraněním, nikoli dětmi.

13
RolandoMySQLDBA

Pokud chcete odstranit rodiče a opustit dítě, pravděpodobně budete chtít ON DELETE SET NULL možnost:

SET NULL: Odstraňte nebo aktualizujte řádek z nadřazené tabulky a nastavte sloupec nebo sloupce cizího klíče v podřízené tabulce na NULL. Jsou podporovány klauzule ON DELETE SET NULL a ON UPDATE SET NULL.

Pokud zadáte akci SET NULL, ujistěte se, že jste nevyhlásili sloupce v podřízené tabulce jako NOT NULL.

V té poslední větě je hodně 'ne', takže se ujistěte, že parent_id může být NULL.

Viz také tato související otázka: Jaký je účel SET NULL v omezeních Odstranit/Aktualizovat cizí klíče?

Definováním cizího klíče jste řekli databázi, aby neakceptovala položky v podřízené tabulce, které nemají nadřazenou hodnotu.

5
Derek Downey