2011-11-30 2 views
18

Ho fatto un errore e devo dividere 1 tabella in 2. Ho una tabella di prodotto e ho bisogno della tabella delle categorie. quando ho iniziato ho avuto solo 1 categoria per prodotto ma non (con nuovi requisiti aziendali) ho bisogno della possibilità di mettere un prodotto in più categorie.mysql che separa le tabelle

Ho un prodotto tabelle che ha una categoria in esso.

ecco la tabella:

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

ora, come posso efficientemente migrare questo senza fare il mio sito offline?

ho lampada su CentOS

+0

la categoria è varchar? –

+0

yes varchar (40) campo non nullo poiché la categoria è richiesta quando si inserisce il prodotto – rcs20

risposta

24

Prima assicurati che le tue categorie siano uniche. Assicurati di non avere qualcosa del tipo:

productx and produtx 

Altrimenti, quando inserirai cattive categorie.

Si dovrà fare in passo:

1) Creazione della categoria tavolo

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; 

creare la tabella di intersezione dal momento che un prodotto può essere in categorie multiple e una categoria può avere più Prodotto.

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) inserisce le categorie nella tabella.

INSERT IGNORE INTO category SELECT DISTINCT category from product; 

Questo inserirà categorie non duplicati nella tabella categoria con un ID univoco.

Ora, bisogna inserisce questi record nella

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) Ora è necessario modificare il codice in modo da utilizzare la query giusta: Esempio:

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) Ora, quando ti senti a tuo agio con le modifiche al codice, puoi rilasciare la colonna non utilizzata:

ALTER TABLE product DROP COLUMN category; 
+4

grazie ho avuto 3 categorie con nome simile e per mettere le query tutte insieme, l'aiuto è apprezzato – rcs20

+0

sei il benvenuto, fammi sapere se hai bisogno di ulteriore aiuto –

+0

domanda: la tua query che hai messo sarà usato per quando io vuoi selezionare i miei prodotti? o categorie? o entrambi? e perché chiave unica nella categoria? – rcs20

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

Quindi aggiungere un vincolo di chiave foriegn su id in new_table_name che fa riferimento alla tabella prodotto originale. Dopo questo è possibile alter table product drop column column_name.

+3

MySQL Server non supporta l'estensione SQL Sybase SELECT ... INTO TABLE. Invece, MySQL Server supporta la sintassi SQL standard di INSERT INTO ... SELECT, che è fondamentalmente la stessa cosa. – favoretti

3

Creazione di una categoria di tabella:

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

Quindi selezionare categorie uniche da tavolo prodotto:

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

quindi creare un tavolo per le relazioni:

CREATE TABLE product_to_category (product_id int, category_id int); 

Se si desidera, è può usare chiavi e vincoli esterni.

Quindi è possibile eseguire la migrazione delle relazioni esistenti:

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

Dopo di che, regolare il codice per utilizzare la nuova struttura e rilasciare la colonna categoria dalla tabella di prodotto:

ALTER TABLE product DROP COLUMN category; 

Spero che questo aiuti.

+0

grazie per il vostro aiuto – rcs20

0

Si potrebbe iniziare normalizzando la vostra tavola prodotto - la creazione di 2 nuove tabelle:

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. 

Poi si dovrebbe creare unisce per ottenere i prodotti per categoria.

+5

OOps, sembra che i favoretti mi abbiano battuto con una soluzione simile – dar7yl

+0

Il vostro è più ordinato dato che in realtà avete impiegato del tempo per includere riferimenti corretti e persino indici! :) – favoretti