我想从"prods"表中删除一行。每当我删除一行时,我都希望它删除与它相关联的其他表中的行
每当我试图使用我的PHP代码从"prods"中删除一行时,我都会收到以下错误:
A Database Error Occurred
Error Number: 1451
Cannot delete or update a parent row: a foreign key constraint fails (`tools`.`keywords`, CONSTRAINT `keywords_ibfk_1` FOREIGN KEY (`key_prod`) REFERENCES `prods` (`prod_id`))
我在"关键字"表中也得到了同样的结果——这是通过删除"数据"表中"相关"的行来解决的,然后再从"关键字"表格中删除该行。
但是,当我从"prods"表中删除一行时再次遇到这个问题时,我注意到这不可能像这样工作,必须有一种更有效的方法来做到这一点。
在谷歌上搜索了一点后,我发现我可能会使用"DELETE Cascade",这可能会导致问题(或删除不需要的行)。我真的不知道它是否会——所以我对此进行了更多的研究。以下其他搜索结果我发现了这篇文章:
无法删除或更新父行:外键约束使失败
这家伙被告知外国钥匙做得不对,他必须在他们之间交换,这将解决他的问题。
我是处理复杂数据库的新手,我想知道我做这件事的方式是否正确——所有的FOREIGN KEY都做得正确,如果我使用DELETE CASCADE
,我会做得正确。
这是我的数据库转储结构(MySQL):
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
-- Table structure for table `prods`
--
CREATE TABLE `prods` (
`prod_id` int(11) NOT NULL,
`prod_name` varchar(255) NOT NULL,
`prod_aaa_id` varchar(255) NOT NULL,
`prod_bbb_id` varchar(255) NOT NULL,
`prod_get_installs` tinyint(1) NOT NULL,
`prod_user` int(11) NOT NULL,
`prod_client_email` varchar(255) NOT NULL,
`prod_client_name` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `prod_data`
--
CREATE TABLE `prod_data` (
`ad_id` int(11) NOT NULL,
`ad_prod` int(11) NOT NULL,
`ad_date` date NOT NULL,
`ad_aaa_inst` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `data`
--
CREATE TABLE `data` (
`id` int(11) NOT NULL,
`dat_id` int(11) NOT NULL,
`dat_date` date NOT NULL,
`dat_rank_aaa` int(11) NOT NULL,
`dat_traffic_aaa` float NOT NULL,
`dat_rank_bbb` int(11) NOT NULL,
`dat_traffic_bbb` float NOT NULL,
`dat_difficulty_aaa` float NOT NULL,
`dat_difficulty_bbb` float NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `keywords`
--
CREATE TABLE `keywords` (
`key_id` int(11) NOT NULL,
`key_word` varchar(255) NOT NULL,
`key_prod` int(11) NOT NULL,
`kay_country` text NOT NULL,
`key_is_wr` tinyint(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `users`
--
CREATE TABLE `users` (
`u_id` int(11) NOT NULL,
`u_name` varchar(255) NOT NULL,
`u_email` varchar(255) NOT NULL,
`u_password` varchar(255) NOT NULL,
`u_permission` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `weekly_report`
--
CREATE TABLE `weekly_report` (
`wr_id` int(11) NOT NULL,
`wr_prod_id` int(11) NOT NULL,
`wr_date` date NOT NULL,
`wr_date1` date NOT NULL,
`wr_date2` date NOT NULL,
`wr_date3` date NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Indexes for dumped tables
--
--
-- Indexes for table `prods`
--
ALTER TABLE `prods`
ADD PRIMARY KEY (`prod_id`),
ADD KEY `prod_user` (`prod_user`),
ADD KEY `prod_user_2` (`prod_user`);
--
-- Indexes for table `prod_data`
--
ALTER TABLE `prod_data`
ADD PRIMARY KEY (`ad_id`),
ADD KEY `ad_prod` (`ad_prod`);
--
-- Indexes for table `data`
--
ALTER TABLE `data`
ADD PRIMARY KEY (`id`),
ADD KEY `dat_id` (`dat_id`);
--
-- Indexes for table `kas`
--
ALTER TABLE `kas`
ADD PRIMARY KEY (`kas_id`);
--
-- Indexes for table `keywords`
--
ALTER TABLE `keywords`
ADD PRIMARY KEY (`key_id`),
ADD KEY `key_prod` (`key_prod`);
--
-- Indexes for table `users`
--
ALTER TABLE `users`
ADD PRIMARY KEY (`u_id`),
ADD KEY `u_id` (`u_id`);
--
-- Indexes for table `weekly_report`
--
ALTER TABLE `weekly_report`
ADD PRIMARY KEY (`wr_id`),
ADD KEY `wr_prod_id` (`wr_prod_id`),
ADD KEY `wr_prod_id_2` (`wr_prod_id`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `prods`
--
ALTER TABLE `prods`
MODIFY `prod_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=23;
--
-- AUTO_INCREMENT for table `prod_data`
--
ALTER TABLE `prod_data`
MODIFY `ad_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=13;
--
-- AUTO_INCREMENT for table `data`
--
ALTER TABLE `data`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3754;
--
--
-- AUTO_INCREMENT for table `keywords`
--
ALTER TABLE `keywords`
MODIFY `key_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=236;
--
-- AUTO_INCREMENT for table `users`
--
ALTER TABLE `users`
MODIFY `u_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7;
--
-- AUTO_INCREMENT for table `weekly_report`
--
ALTER TABLE `weekly_report`
MODIFY `wr_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7;
--
-- Constraints for dumped tables
--
--
-- Constraints for table `prods`
--
ALTER TABLE `prods`
ADD CONSTRAINT `prods_ibfk_1` FOREIGN KEY (`prod_user`) REFERENCES `users` (`u_id`);
--
-- Constraints for table `data`
--
ALTER TABLE `data`
ADD CONSTRAINT `data_ibfk_1` FOREIGN KEY (`dat_id`) REFERENCES `keywords` (`key_id`);
--
-- Constraints for table `keywords`
--
ALTER TABLE `keywords`
ADD CONSTRAINT `keywords_ibfk_1` FOREIGN KEY (`key_prod`) REFERENCES `prods` (`prod_id`);
--
-- Constraints for table `weekly_report`
--
ALTER TABLE `weekly_report`
ADD CONSTRAINT `weekly_report_ibfk_1` FOREIGN KEY (`wr_prod_id`) REFERENCES `prods` (`prod_id`);
你能告诉我外国钥匙做得对吗?我应该改变我的结构吗?
在这种情况下,"级联"是否可以正常工作?
非常感谢。
编辑:
这就是造成所有问题的原因吗?
ALTER TABLE `keywords`
ADD CONSTRAINT `keywords_ibfk_1` FOREIGN KEY (`key_prod`) REFERENCES `prods` (`prod_id`);
如果是的话,在目前的状态下,有了我数据库中目前的所有数据,我如何取消它并在没有错误的情况下翻转它?
有关当前结构的更多信息:
- 每个"prod"都有一个以上的关键字("keywords"表)
- 每个"关键字"都有多个"数据"行
- 每个"prod"只有一个用户
- 每个"prod"都有多个"prod_data"
因此,为了确定起见,请遵循以下简短的解释:http://www.w3schools.com/sql/sql_foreignkey.asp
"key_prod"显然是"keywords"表中的FOREIGN key,"prod_id"是"prods"表中"PRIMARY key"。
我现在很困惑。
编辑#2:
这是我发现的另一个解决方案,不太确定如何在我的代码中应用它,但无论如何:
简单的方法是禁用外键检查;使更改后重新启用外键检查。
SET FOREIGN_KEY_CHECKS=0; -- to disable them SET FOREIGN_KEY_CHECKS=1; -- to re-enable them
我不确定这是一种变通方法,还是这类问题的真正解决方案,我真的希望我的代码能"按书"工作,尤其是当我刚开始处理这类问题时。
我曾处理过类似的数据库项目。首先备份数据库。
试着丢掉你的外国钥匙。
ALTER TABLE table_name DROP FOREIGN KEY column_name_ibfk_1;
之后,您现在可以创建一个外键,该外键可以执行上述行为。
ALTER TABLE table_name ADD FOREIGN KEY(column_name) REFERENCES table_name(column_name) ON DELETE CASCADE ON UPDATE CASCADE;