外键约束对一对一关系没有影响

时间:2015-10-19 21:59:53

标签: mysql sql

我有2个表test1test2,它们共享了一些属性,因此我创建了一个包含共享属性的新表properties

问题是删除级联不起作用,因为当我从properties删除记录时,它仍然存在于test1test2中,反之亦然而且看来是外国的关键约束根本没有效果。

test1

CREATE TABLE `test1` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `properties` int(10) unsigned DEFAULT NULL,
  ....
  PRIMARY KEY (`id`),
  KEY `..` (`properties`),
  CONSTRAINT `..` FOREIGN KEY (`properties`) REFERENCES `properties` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE,
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;

test2

CREATE TABLE `test2` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `properties` int(10) unsigned DEFAULT NULL,
  .....
  PRIMARY KEY (`id`),
  KEY `..` (`properties`),
  CONSTRAINT `..` FOREIGN KEY (`properties`) REFERENCES `properties` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

PROPERTIES

CREATE TABLE `properties` (
  `ID` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `test1` int(10) unsigned DEFAULT NULL,
  `test2` int(10) unsigned DEFAULT NULL,
  ....

  PRIMARY KEY (`ID`),
  KEY `..` (`ao`),
  KEY `..` (`enchere`),
  CONSTRAINT `..` FOREIGN KEY (`test1`) REFERENCES `test1` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `..` FOREIGN KEY (`test2`) REFERENCES `test2` (`id`) ON DELETE CASCADE ON UPDATE CASCADE

) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;

1 个答案:

答案 0 :(得分:1)

-- drop schema tomfoolery;
create schema tomfoolery; -- create and use this db/schema so as not to pollute your world
use tomfoolery;
CREATE TABLE `test1` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `properties` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY (`properties`)
  -- CONSTRAINT FOREIGN KEY (`properties`) REFERENCES `properties` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `test2` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `properties` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY (`properties`)
  -- CONSTRAINT FOREIGN KEY (`properties`) REFERENCES `properties` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `properties` (
  `ID` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `test1` int(10) unsigned DEFAULT NULL,
  `test2` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`ID`)
  -- CONSTRAINT FOREIGN KEY (`test1`) REFERENCES `test1` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  -- CONSTRAINT FOREIGN KEY (`test2`) REFERENCES `test2` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

alter table test1 add constraint FOREIGN KEY (`properties`) REFERENCES `properties` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE;
alter table test2 add constraint FOREIGN KEY (`properties`) REFERENCES `properties` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE;
alter table properties add CONSTRAINT FOREIGN KEY (`test1`) REFERENCES `test1` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
alter table properties add CONSTRAINT FOREIGN KEY (`test2`) REFERENCES `test2` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;

没有上述内容,至少我无法正确设置您的架构。我想我可以在创建之前关闭FK检查。请参阅下面的架构:

show create table test1;
show create table test2;
show create table properties;

- 架构似乎正确,现在

由于循环性质,打开和关闭FK检查似乎是维持此设置生活的唯一方法

SET FOREIGN_KEY_CHECKS=1; -- circular so don't check. Note that the below nulls work with check off, but won't work below with not null, so we are doing this here
insert test1(properties) values (null); -- ok
insert test2(properties) values (null); -- ok
insert properties(test1,test2) values (null,null); -- ok

SET FOREIGN_KEY_CHECKS=0; -- circular so don't check. Note above works with null but won't work below so we are doing this here
-- again, without the above SET, the following will fail with error 1452
insert test1(properties) values (2); -- ok
insert test2(properties) values (2); -- ok
insert properties(test1,test2) values (2,2); -- ok

SET FOREIGN_KEY_CHECKS=1; -- must turn this back on else cascades will not work
select * from test1;
select * from test2;
select * from properties;
-- note that all 3 tables above have 2 rows with id's 1 and 2

-- now see the cascade deletes will magically work (that is test1 and test2 will have id2 deleted too after the below command)
delete from properties where id=2; -- 1 row affected
use tomfoolery; -- sometimes without doing this, a weird error occurs below saying Error: Error formatting SQL query: empty string given as argument for ! character

select * from test1;
select * from test2;
select * from properties;

在test1,test2

上级联删除成功

Foreign Key Constraints上的一般手册页,以便开始使用。

因为它们是一对一的,所以很多人会说,无论如何,只要把这些东西放在原生表中,如OP所提到的那样。但它似乎是一个挑战,所以就是这样。

相关问题