我有三张桌子: 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)
据我所知,这不应该发生。任何想法为什么会这样?
答案 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。尽管它应该这样做,但这可能并不总是显而易见的。