2011-11-30 73 views
18

我犯了一个错误,我必须将1表分成2个。我有一个产品表,我需要分类表。当我开始的时候,我只有每个产品有1个类别,但没有(有新的业务需求),我需要把产品放在多个类别中的能力。mysql分离表

我有一个产品表中有一个类别。

这里的表:

product (id, name, category, price etc...) 

现在,我怎样才能有效地迁移这一点没有让我的网站下线?

我已经在CentOS

+0

category is varchar? –

+0

yes varchar(40)非空字段,因为插入产品时需要该类别 – rcs20

回答

24

首先确保您的类别是唯一的。确保你没有这样的东西:

productx and produtx 

否则,当你将插入不好的类别。

你将不得不做,在步:

1)创建表类别

CREATE TABLE `category` (
    `id` int(10) unsigned NOT NULL auto_increment, 
    `name` varchar(40) NOT NULL DEFAULT 'General', 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `name` (`name`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 

创建交集表,因为产品可以在多个类别和种类可以有多个产品。

CREATE TABLE `product_category` (
    `product_id` int(10) unsigned NOT NULL, 
    `category_id` int(10) unsigned NOT NULL, 
PRIMARY KEY product_category (`product_id`,`category_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 

2)将类别插入表中。

INSERT IGNORE INTO category SELECT DISTINCT category from product; 

这将使用唯一的ID插入非重复类别到类别表中。现在

,你在

INSERT IGNORE INTO `product_category` SELECT `product`.`id` AS `product_id`, `category`.`id` AS `category_id` FROM `category` LEFT JOIN `product` ON (`category`.`name` = `product`.`category`); 

3插入这些记录),现在你必须修改代码以使用正确的查询: 例子:

SELECT 
/* your fields */ 
FROM 
product 
INNER JOIN product_category ON (product.id = product_category.product_id) 
INNER JOIN category ON (category.id = product_category.category_id) 
WHERE ... 

4)现在,当您对代码更改感到满意时,可以删除未使用的列:

ALTER TABLE product DROP COLUMN category; 
+4

谢谢我有3类与名称相似,并把查询所有在一起,你的帮助表示赞赏 – rcs20

+0

你非常欢迎,让我知道,如果你需要额外的帮助 –

+0

问题:你的查询你把它将用于当我想要选择我的产品?或类别?或两者?以及为什么类别上的唯一键? – rcs20

0
INSERT INTO new_table_name ("product", "category") 
SELECT id, category 
FROM product; 

灯然后加在new_table_name ID的foriegn键约束它引用原始的产品表。在此之后,您可以alter table product drop column column_name

+3

MySQL服务器不支持SELECT ... INTO TABLE Sybase SQL扩展。相反,MySQL服务器支持INSERT INTO ... SELECT标准SQL语法,它基本上是一样的。 – favoretti

3

创建一个表类:

CREATE TABLE category(id int primary key not null auto_increment, category varchar(40)) 

然后选择从产品表中是唯一的类别:

INSERT INTO category (category) SELECT DISTINCT category FROM product; 

然后创建一个表关系:

CREATE TABLE product_to_category (product_id int, category_id int); 

如果你愿意,你可以使用外键和约束。

然后你就可以迁移现有的关系:

INSERT INTO product_to_category SELECT product.id, category.id FROM product JOIN category on category.category=product.category; 

之后,调整您的代码以使用新的结构,并从产品表中删除类别栏:

ALTER TABLE product DROP COLUMN category; 

希望这有助于。

+0

感谢您的帮助 – rcs20

0

你会通过标准化产品表开始 - 创建2个新表:

CREATE TABLE categories 
(
    cat_id int AUTO_INCREMENT NOT NULL PRIMARY KEY, 
    cat_label varchar(40) 
); 

CREATE TABLE product_by_category 
(
    pbc_prod_id int REFERENCES products(id), 
    pbc_cat_id int REFERENCES categories(cat_id), 
    #indexes for quicker lookup... 
    INDEX pbc(pbc_prod_id,pbc_cat_id), 
    INDEX cbp(pbc_cat_id, pbc_prod_id) 
); 



    INSERT INTO categories(cat_label) SELECT DISTINCT category FROM product; 
    INSERT INTO product_by_category(pbc_prod_id, pbc_cat_id) 
     SELECT id, (SELECT cat_id FROM categories WHERE categories.cat_label = product.category) 
     FROM products; 

    ALTER TABLE products DROP COLUMNN category; #do this after you are satisfied with contents of new tables. 

然后,你就必须创建的连接为获得产品按类别。

+5

OOps,它看起来像favoretti击败我与此类似的解决方案 – dar7yl

+0

你真的很花时间,包括适当的参考,甚至索引! :) – favoretti