即使使用 SET FOREIGN_KEY_CHECKS=0 也无法创建表(错误 1215);

Posted

技术标签:

【中文标题】即使使用 SET FOREIGN_KEY_CHECKS=0 也无法创建表(错误 1215);【英文标题】:Can't create table (ERROR 1215) even with SET FOREIGN_KEY_CHECKS=0; 【发布时间】:2016-04-14 08:12:26 【问题描述】:

我正在尝试做的事情我已经做了无数次,但现在从 mysql 5.6.26 升级到 5.6.27 失败了(在 5.7.x 中也失败了)。我有一个数据库,其中包含一堆具有外键约束的表。我已导出(使用 phpMyAdmin)替换表,指定了以下导出选项:

Disable foreign key checks
Add DROP TABLE / VIEW / PROCEDURE / FUNCTION / EVENT / TRIGGER statement
Add CREATE TABLE statement

生成的导出文件部分包含:

SET FOREIGN_KEY_CHECKS=0;

DROP TABLE IF EXISTS `application`;
CREATE TABLE `application` (
  `PK_Application` int(11) NOT NULL,
  `FK_Parent` int(11) DEFAULT NULL,
  `ApplicationLevel` tinyint(4) NOT NULL,
  `Description` varchar(35) NOT NULL,
  `Sequence` tinyint(4) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=latin1;

. . .
. . .

DROP TABLE IF EXISTS `product_x_application`;
CREATE TABLE `product_x_application` (
  `PK_Product_X_Application` int(11) NOT NULL,
  `Product_PKID` varchar(36) NOT NULL,
  `FK_Application` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

. . .
. . .

ALTER TABLE `product_x_application`
  ADD CONSTRAINT `product_x_application_ibfk_2` FOREIGN KEY (`FK_Application`) REFERENCES `application` (`PK_Application`) ON DELETE CASCADE ON UPDATE CASCADE;

当表applicationproduct_x_application 已经存在时,当此文件输入到mysql.exe 或phpMyAdmin 导入函数时,表application 的DROP 语句成功但随后的CREATE TABLE 语句失败:

ERROR 1215 (HY000): 无法添加外键约束

但是,如果我首先删除 product_x_application 表,该表具有引用表 application 的外键约束 product_x_application_ibfk_2,则 CREATE TABLE 语句会成功。

我从那以后了解了更多信息。我走到我的生产机器上,它运行带有 MySql 5.5 服务器和 phpMyAdmin 4.4.23 phpMyAdmin 的 Linux,并且只导出了两个有问题的表,并且能够将生成的文件导入我的 MySql 5.6.27 服务器.这是两个完整导出文件(仅结构)。首先来自有问题的 5.6.27 服务器:

-- phpMyAdmin SQL Dump
-- version 4.4.15
-- http://www.phpmyadmin.net
--
-- Host: localhost
-- Generation Time: Jan 10, 2016 at 07:01 AM
-- Server version: 5.6.26-log
-- PHP Version: 5.6.12

SET FOREIGN_KEY_CHECKS=0;
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;

--
-- Database: `spmorell_sami`
--

-- --------------------------------------------------------

--
-- Table structure for table `application`
--

DROP TABLE IF EXISTS `application`;
CREATE TABLE `application` (
  `PK_Application` int(11) NOT NULL,
  `FK_Parent` int(11) DEFAULT NULL,
  `ApplicationLevel` tinyint(4) NOT NULL,
  `Description` varchar(35) NOT NULL,
  `Sequence` tinyint(4) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

-- --------------------------------------------------------

--
-- Table structure for table `product_x_application`
--

DROP TABLE IF EXISTS `product_x_application`;
CREATE TABLE `product_x_application` (
  `PK_Product_X_Application` int(11) NOT NULL,
  `Product_PKID` varchar(36) NOT NULL,
  `FK_Application` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Indexes for dumped tables
--

--
-- Indexes for table `application`
--
ALTER TABLE `application`
  ADD PRIMARY KEY (`PK_Application`);

--
-- Indexes for table `product_x_application`
--
ALTER TABLE `product_x_application`
  ADD PRIMARY KEY (`PK_Product_X_Application`),
  ADD KEY `Product_PKID` (`Product_PKID`),
  ADD KEY `FK_Application` (`FK_Application`);

--
-- AUTO_INCREMENT for dumped tables
--

--
-- AUTO_INCREMENT for table `application`
--
ALTER TABLE `application`
  MODIFY `PK_Application` int(11) NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT for table `product_x_application`
--
ALTER TABLE `product_x_application`
  MODIFY `PK_Product_X_Application` int(11) NOT NULL AUTO_INCREMENT;
--
-- Constraints for dumped tables
--

--
-- Constraints for table `product_x_application`
--
ALTER TABLE `product_x_application`
  ADD CONSTRAINT `product_x_application_ibfk_1` FOREIGN KEY (`Product_PKID`) REFERENCES `product` (`Product_PKID`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `product_x_application_ibfk_2` FOREIGN KEY (`FK_Application`) REFERENCES `application` (`PK_Application`) ON DELETE CASCADE ON UPDATE CASCADE;
SET FOREIGN_KEY_CHECKS=1;

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

请注意,application 表的主键是在 ALTER TABLE 语句中定义的。这是从 5.5 服务器导出的文件:

-- phpMyAdmin SQL Dump
-- version 3.5.8.2
-- http://www.phpmyadmin.net
--
-- Host: localhost
-- Generation Time: Jan 10, 2016 at 05:09 AM
-- Server version: 5.5.42-37.1-log
-- PHP Version: 5.4.23

SET FOREIGN_KEY_CHECKS=0;
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";

--
-- Database: `spmorell_sami`
--

-- --------------------------------------------------------

--
-- Table structure for table `application`
--

DROP TABLE IF EXISTS `application`;
CREATE TABLE `application` (
  `PK_Application` int(11) NOT NULL AUTO_INCREMENT,
  `FK_Parent` int(11) DEFAULT NULL,
  `ApplicationLevel` tinyint(4) NOT NULL,
  `Description` varchar(35) NOT NULL,
  `Sequence` tinyint(4) NOT NULL,
  PRIMARY KEY (`PK_Application`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=15 ;

-- --------------------------------------------------------

--
-- Table structure for table `product_x_application`
--

DROP TABLE IF EXISTS `product_x_application`;
CREATE TABLE `product_x_application` (
  `PK_Product_X_Application` int(11) NOT NULL AUTO_INCREMENT,
  `Product_PKID` varchar(36) NOT NULL,
  `FK_Application` int(11) NOT NULL,
  PRIMARY KEY (`PK_Product_X_Application`),
  KEY `Product_PKID` (`Product_PKID`),
  KEY `FK_Application` (`FK_Application`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1633 ;

--
-- Constraints for dumped tables
--

--
-- Constraints for table `product_x_application`
--
ALTER TABLE `product_x_application`
  ADD CONSTRAINT `product_x_application_ibfk_2` FOREIGN KEY (`FK_Application`) REFERENCES `application` (`PK_Application`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `product_x_application_ibfk_1` FOREIGN KEY (`Product_PKID`) REFERENCES `product` (`Product_PKID`) ON DELETE CASCADE ON UPDATE CASCADE;
SET FOREIGN_KEY_CHECKS=1;

这里application 表的主键在定义表时立即定义。我认为问题在于product_x_application 表在系统尝试重新创建application 表时已经存在,它对重新创建时没有所需索引的表有一个外键约束外键,因为尚未定义主键。

【问题讨论】:

禁用外键检查适用于插入、更新和删除,不适用于创建或修改表。 如果我尝试删除表 application 我得到错误 1217 (23000):无法删除或更新父行:外键约束失败,但如果我设置了 FOREIGN_KEY_CHECKS=0;,那么我可以滴。所以 FOREIGN_KEY_CHECKS 与表的创建和删除有关。问题是我有一个包含 N 个表的数据库。其中一个子集 M 是在外部生成的,我需要用这些表替换数据库上的 M 个现有表。我怀疑我可以通过先明确设置 FOREIGN_KEY_CHECKS=0 并在导入之前删除 M 表来做到这一点,但是,多么痛苦! 当您删除包含被外键引用的记录的父表时,删除父记录是违反外键的。因此,它与 drop table 无关。想想丢桌子的副作用吧。 【参考方案1】:

我有更多信息。我已经安装了更高版本的 phpMyAdmin (4.5.0.2),但忘记了。为了咯咯笑,我决定用它来做出口。和以前一样,我将 ADD DROP TABLE 指定为选项(自动选中 ADD CREATE TABLE,不能取消选中)。但是现在,在 ADD CREATE TABLE 的 IF NOT EXISTS 子选项旁边,它在括号中说:“(效率较低,因为在创建表期间会生成索引)”,这当然正是我需要的(通常我不会认为检查此选项,因为我知道此时该表不可能存在)。输出是:

-- phpMyAdmin SQL Dump
-- version 4.5.0.2
-- http://www.phpmyadmin.net
--
-- Host: localhost
-- Generation Time: Jan 10, 2016 at 07:54 AM
-- Server version: 5.6.26-log
-- PHP Version: 5.6.12

SET FOREIGN_KEY_CHECKS=0;
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";

--
-- Database: `spmorell_sami`
--

-- --------------------------------------------------------

--
-- Table structure for table `application`
--

DROP TABLE IF EXISTS `application`;
CREATE TABLE IF NOT EXISTS `application` (
  `PK_Application` int(11) NOT NULL AUTO_INCREMENT,
  `FK_Parent` int(11) DEFAULT NULL,
  `ApplicationLevel` tinyint(4) NOT NULL,
  `Description` varchar(35) NOT NULL,
  `Sequence` tinyint(4) NOT NULL,
  PRIMARY KEY (`PK_Application`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=latin1;

-- --------------------------------------------------------

--
-- Table structure for table `product_x_application`
--

DROP TABLE IF EXISTS `product_x_application`;
CREATE TABLE IF NOT EXISTS `product_x_application` (
  `PK_Product_X_Application` int(11) NOT NULL AUTO_INCREMENT,
  `Product_PKID` varchar(36) NOT NULL,
  `FK_Application` int(11) NOT NULL,
  PRIMARY KEY (`PK_Product_X_Application`),
  KEY `Product_PKID` (`Product_PKID`),
  KEY `FK_Application` (`FK_Application`)
) ENGINE=InnoDB AUTO_INCREMENT=1633 DEFAULT CHARSET=latin1;

--
-- Constraints for dumped tables
--

--
-- Constraints for table `product_x_application`
--
ALTER TABLE `product_x_application`
  ADD CONSTRAINT `product_x_application_ibfk_1` FOREIGN KEY (`Product_PKID`) REFERENCES `product` (`Product_PKID`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `product_x_application_ibfk_2` FOREIGN KEY (`FK_Application`) REFERENCES `application` (`PK_Application`) ON DELETE CASCADE ON UPDATE CASCADE;
SET FOREIGN_KEY_CHECKS=1;

所以问题一直是 phpMyadmin 4.4.15 版本而不是 MySql 版本。显然,我一直在定期升级 phpMyAdmin 版本,我可以推断出我从来没有机会使用有问题的(至少对我而言)phpMyAdmin 版本 4.4.15 运行导入。

【讨论】:

【参考方案2】:

外键应引用唯一列(例如,主键)。 PK_Application,目前还不是这样的专栏。不过,从它的名字来看,您似乎打算将它作为主键:

ALTER TABLE `application` 
ADD CONSTRAINT `application_pk` PRIMARY KEY (`PK_Application`);

【讨论】:

我指定我“部分”包含 DDL。我省略了其他通过 ALTER TABLE 语句为 application table 指定主键的 DDL 语句。 @RonaldAaronson 为什么 pk 约束在 alter table 而不是 create table 中定义? 这就是当您执行 phpMyAdmin 导出操作时 phpMyAdmin 和/或 MySql 生成输出文件的方式(这不是我最初定义表的方式)。我无法确定该行为是 phpMyAdmin 还是 MySql 的函数。 @Mureinik 查看我的回答:虽然是在 ALTER TABLE 语句中定义了主键,但这是 phpMyAdmin 特定版本的一个特点,它是我所有困境的原因。

以上是关于即使使用 SET FOREIGN_KEY_CHECKS=0 也无法创建表(错误 1215);的主要内容,如果未能解决你的问题,请参考以下文章

即使使用 SET FOREIGN_KEY_CHECKS=0 也无法创建表(错误 1215);

在 Windows 环境中,如果 GPU 已经使用,Cupy 在 multithread.pool 中会出错,即使我使用了 multiprocessing.set_start_method('spaw

即使响应包含 ajax 请求的“Set-Cookie”标头,cookie 也不会存储在浏览器中

即使响应包含ajax请求的“Set-Cookie”标头,cookie也不会存储在浏览器中

即使将 <uses-permission> 用于 SET_ALARM,也会获得 Permission Denial?

SQL Server 错误:“无法为标识列插入显式值”,即使我 SET IDENTITY_INSERT ON