意外的MySQL"外键约束失败。"信息

时间:2017-01-02 09:39:07

标签: mysql

我有三张桌子: sa_Zona sa_Regiune sa_ZonaLista

CREATE TABLE sa_Zona (
   zona_id SMALLINT UNSIGNED NOT NULL,

   regiune_fk SMALLINT UNSIGNED NOT NULL DEFAULT 65499,
   coronim_fk SMALLINT UNSIGNED NOT NULL DEFAULT 65499,

   nadir VARCHAR(3) NOT NULL DEFAULT '',
   ord_ TINYINT UNSIGNED NOT NULL DEFAULT 1,
     INDEX(ord),

   delim VARCHAR(3) NOT NULL DEFAULT '.',
   incert VARCHAR(2) NOT NULL DEFAULT '',
   obs VARCHAR(50)  CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '',

   data_mod TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

   PRIMARY KEY (zona_id, coronim_fk, ord)
   )
ENGINE=InnoDB
DEFAULT CHARACTER SET=latin1
COLLATE=latin1_general_ci;

ALTER TABLE sa_Zona ADD FOREIGN KEY (coronim_fk) 
   REFERENCES sa_Coronim (coronim_id)
   ON UPDATE CASCADE ON DELETE RESTRICT;

ALTER TABLE sa_Zona ADD FOREIGN KEY (regiune_fk) 
   REFERENCES sa_Regiune (regiune_id)
   ON UPDATE CASCADE ON DELETE RESTRICT;


CREATE TABLE sa_ZonaLista (
   zonalista_id SMALLINT UNSIGNED NOT NULL,

   regiune_fk SMALLINT UNSIGNED NOT NULL DEFAULT 65499,
   nume_zl VARCHAR(200) NOT NULL DEFAULT '',
     INDEX(nume_zl),

   data_mod TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

   PRIMARY KEY (zonalista_id)
   )
ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8
COLLATE= utf8_general_ci;

ALTER TABLE sa_ZonaLista ADD FOREIGN KEY (zonalista_id) 
   REFERENCES sa_Zona (zona_id)
   ON UPDATE CASCADE ON DELETE RESTRICT;

ALTER TABLE sa_ZonaLista ADD FOREIGN KEY (regiune_fk) 
   REFERENCES sa_Zona (regiune_fk)
   ON UPDATE CASCADE ON DELETE RESTRICT;


CREATE TABLE sa_Regiune (
   regiune_id SMALLINT UNSIGNED NOT NULL,

   nume_reg VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci
     NOT NULL DEFAULT '',
     INDEX(nume_reg),
   ord_ SMALLINT UNSIGNED NOT NULL DEFAULT 1,

   data_mod TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
     INDEX(data_mod),

   PRIMARY KEY (regiune_id)
   )
ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8 
COLLATE=utf8_general_ci;

表sa_ZonaLista和sa_Zona具有相同的行数,并且zona_id = zonalista_id和regiune_fk = regiune_fk,因为sa_ZonaLista就像sa_Zona的VIEW生成到表中以便更快地访问时间。因此,每次我需要从sa_Zona中删除一行时(很少发生),我还需要从sa_ZonaLista中删除相应的行以保持一致性。

执行此操作时,可以删除sa_ZonaLista中的一行没有问题,但是当我尝试从sa_Zona中删除相应的行时,我收到此意外消息:

#1451 - Cannot delete or update a parent row: a foreign key constraint fails (`floramv`.`sa_zonalista`, CONSTRAINT `sa_zonalista_ibfk_2` FOREIGN KEY (`regiune_fk`) REFERENCES `sa_zona` (`regiune_fk`) ON UPDATE CASCADE)

据我所知,这不应该发生。任何想法为什么会这样?

2 个答案:

答案 0 :(得分:1)

错误是自解释的,无法删除或更新父行:外键约束失败

表示某些表中存在子记录,该记录与您要删除的记录绑定,如果父记录中有子记录,则无法删除任何父记录。

你有子记录,所以你已经把ON DELETE RESTRICT以及ON UPDATE RESTRICT约束(我的意思是默认),你在父行上所做的任何改变,即korisnici表中包含子行的行slike表将受到MySQL的限制。

现在要删除,你可以这样做:

ON DELETE 约束更改为CASCADE

{{1}}

答案 1 :(得分:0)

@Mayank Pandeyz的回答在我的脑海中突出了完整的正确答案:由于现在在sa_ZonaLista中定义了regiune_fk,当删除sa_Zona的记录时,MySQL也会删除sa_ZonaLista中具有相同product_fk值的子记录。从业务逻辑的角度来看,这是不正确的,但是来自regiune_fk应该已经链接到 regiune信息的正确保管这一事实,即使用regiune_id作为主键的sa_Regiune。并且,sa_ZonaLista中的外键最终应该在生产环境中定义 - 更新CASCADE ON DELETE CASCADE(请参阅我的上一条评论)。一般来说,如果table_A有多个外键,那么table_A 的父表中的任何删除都会提示删除table_A - 如果键的值重合,则AND ON DELETE设置为CASCADE。尽管它应该这样做,但这可能并不总是显而易见的。