MySQL innoDB外键从三个表中删除级联

时间:2014-02-24 19:26:38

标签: php mysql

我有一个包含多个表的MySQL数据库,与链接表连接。我的问题是DELETE语句非常复杂。因此,为了使它们更简单,我尝试使用级联删除来设置外键。

这是我的表结构

--------------
-n_size_class-
--------------
-s_id        -
-s_name      -
--------------

-------------
-n_size_rows-
-------------
-sr_id      -
-sr_name    -
-sr_value   -
-------------

----------------
-n_size_columns-
----------------
-sc_id         -
-sc_name       -
-sc_value      -
----------------

-----------------
-n_size_row_link-
-----------------
-srl_id         -
-srl_size       -
-srl_row        -
-----------------

-----------------
-n_size_col_link-
-----------------
-scl_id         -
-scl_size       -
-scl_col        -
-----------------

这个想法是n_size_class表是主要对象(大小类),然后行和列是size类的子节点。然后使用链接表将行和列绑定到size类。以前,我的插入工作正常,删除是一个问题。现在我尝试设置删除级联,我的插入被破坏(但我的删除工作正常)。我的目标是使插入正常工作,插入size_class,然后对于每一行,它插入到size_row中,然后也插入到size_row_link中,对于列也是如此。然后,当您只删除size_class时,也会删除所有链接,行和列。

外键/级联这些表的正确方法是什么?现在,当我尝试在列或行表中插入任何内容时,我收到外键约束错误。

根据请求,创建语句:

CREATE TABLE `n_size_class` (
  `s_id` int(11) NOT NULL auto_increment,
  `s_name` text NOT NULL,
  PRIMARY KEY  (`s_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

CREATE TABLE `n_size_columns` (
  `sc_id` int(11) NOT NULL auto_increment,
  `sc_name` text NOT NULL,
  `sc_value` text NOT NULL,
  PRIMARY KEY  (`sc_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

CREATE TABLE `n_size_rows` (
  `sr_id` int(11) NOT NULL auto_increment,
  `sr_name` text NOT NULL,
  `sr_value` text NOT NULL,
  PRIMARY KEY  (`sr_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

CREATE TABLE `n_size_row_link` (
  `srl_id` int(11) NOT NULL auto_increment,
  `srl_size` int(11) NOT NULL,
  `srl_row` int(11) NOT NULL,
  PRIMARY KEY  (`srl_id`),
  KEY `srl_row` (`srl_row`),
  KEY `srl_size` (`srl_size`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

CREATE TABLE `n_size_col_link` (
  `scl_id` int(11) NOT NULL auto_increment,
  `scl_size` int(11) NOT NULL,
  `scl_col` int(11) NOT NULL,
  PRIMARY KEY  (`scl_id`),
  KEY `scl_col` (`scl_col`),
  KEY `scl_size` (`scl_size`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

1 个答案:

答案 0 :(得分:2)

我看到它的方式你有三个对象:大小,行和列。

我假设:

  • 链接表是因为可以将大小分配给多个行/列,而行/列可以有多个大小。
  • 当删除大小时,应删除分配,而不删除行/列。
  • 删除行/列时,应删除分配,而不是大小本身。

所以:

CREATE TABLE sizes (
  size_id INTEGER UNSIGNED AUTO_INCREMENT,
  size_name VARCHAR(255),
  ...
  PRIMARY KEY(size_id)
);

CREATE TABLE rows (
  row_id INTEGER UNSIGNED AUTO_INCREMENT,
  ...
  PRIMARY KEY(row_id)
);

CREATE TABLE columns (
  col_id INTEGER UNSIGNED AUTO_INCREMENT,
  ...
  PRIMARY KEY(col_id)
);

CREATE TABLE l_row_size (
  row_id INTEGER UNSIGNED,
  size_id INTEGER UNSIGNED,
  PRIMARY KEY(row_id, size_id),
  CONSTRAINT FOREIGN KEY l_row_size-row_id (row_id) REFERENCES rows (row_id) ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT FOREIGN KEY l_row_size-size_id (size_id) REFERENCES sizes (size_id) ON UPDATE CASCADE ON DELETE CASCADE
);


CREATE TABLE l_col_size (
  col_id INTEGER UNSIGNED,
  size_id INTEGER UNSIGNED,
  PRIMARY KEY(col_id, size_id),
  CONSTRAINT FOREIGN KEY l_col_size-row_id (col_id) REFERENCES rows (col_id) ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT FOREIGN KEY l_col_size-size_id (size_id) REFERENCES sizes (size_id) ON UPDATE CASCADE ON DELETE CASCADE
);

然后:

foreach( $sizes as $size ) {
  $dbh->query("INSERT INTO sizes (size_name) VALUES ('{$size['name']}')");
  $size_id = $dbh->last_insert_id();

  foreach( $rows as $row ) {
    $dbh->query("INSERT INTO l_row_size (size_id, row_id) VALUES ($size_id, {$row['id']})");
  }

  foreach( $cols as $col ) {
    $dbh->query("INSERT INTO l_col_size (size_id, col_id) VALUES ($size_id, {$col['id']})");
  }
}

修改

Sharf评论道:

  

每个Size Class可以包含许多行和多列,但每个行和列只能属于一个大小类。

那么你只需要3个表:

CREATE TABLE sizes (
  size_id INTEGER UNSIGNED AUTO_INCREMENT,
  ...
  PRIMARY KEY(size_id)
);

CREATE TABLE rows (
  row_id INTEGER UNSIGNED AUTO_INCREMENT,
  size_id INTEGER UNSIGNED,
  ...
  PRIMARY KEY(row_id)
  CONSTRAINT FOREIGN KEY rows-size_id (size_id) REFERENCES sizes (size_id) ON UPDATE CASCADE ON DELETE CASCADE,
);

CREATE TABLE columns (
  col_id INTEGER UNSIGNED AUTO_INCREMENT,
  size_id INTEGER UNSIGNED,
  ...
  PRIMARY KEY(col_id),
  CONSTRAINT FOREIGN KEY cols-size_id (size_id) REFERENCES sizes (size_id) ON UPDATE CASCADE ON DELETE CASCADE,
);

链接表仅在n:m关系的情况下才真正有用,这是两个1:n关系的情况。每个Row / Column对象只需要存储对它们所属的Size的引用。