我有一个包含多个表的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;
答案 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的引用。