2010-03-02 13 views
7

stavo migrando database MySQL per Postgres e ci siamo imbattuti il ​​seguente blocco nel DDL (Nota: Questo è quello che ho ottenuto da mysqldump):Chiave straniera Mysql con chiave non univoca - come è possibile?

CREATE TABLE `catalog_property_value` (
    `id` int(10) unsigned NOT NULL, 
    `property_id` int(10) unsigned NOT NULL, 
    `sort` int(10) unsigned NOT NULL, 
    `value_number` decimal(15,5) DEFAULT NULL, 
    `value_string` varchar(255) DEFAULT NULL, 
    PRIMARY KEY (`id`,`sort`), 
    KEY `FK_catalog_property_value` (`property_id`), 
    KEY `NewIndex1` (`id`), 
    CONSTRAINT `FK_catalog_property_value` FOREIGN KEY (`property_id`) REFERENCES `catalog_property` (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
SET character_set_client = @saved_cs_client; 

CREATE TABLE `catalog_realty_property_value_link` (
    `realty_id` int(10) unsigned NOT NULL, 
    `property_id` int(10) unsigned NOT NULL, 
    `value_id` int(10) unsigned NOT NULL, 
    `dt_is_denormalized` tinyint(1) unsigned NOT NULL, 
    PRIMARY KEY (`realty_id`,`property_id`,`value_id`), 
    KEY `FK_catalog_realty_property_value_link_property` (`property_id`), 
    KEY `FK_catalog_realty_property_value_link_value` (`value_id`), 
    CONSTRAINT `FK_catalog_realty_property_value_link_property` FOREIGN KEY (`property_id`) REFERENCES `catalog_property` (`id`) ON DELETE CASCADE, 
    CONSTRAINT `FK_catalog_realty_property_value_link_realty` FOREIGN KEY (`realty_id`) REFERENCES `catalog_realty` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, 
    CONSTRAINT `FK_catalog_realty_property_value_link_value` FOREIGN KEY (`value_id`) REFERENCES `catalog_property_value` (`id`) ON DELETE CASCADE 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

Ora, quello che vedo qui è che l'unica chiave unica nel prima tabella è una combinazione di (id, specie):

PRIMARY KEY (`id`,`sort`), 

tuttavia, la seconda tabella ha un riferimento alla prima il da colonna id unico, non riservate!

CONSTRAINT `FK_catalog_realty_property_value_link_value` FOREIGN KEY (`value_id`) REFERENCES `catalog_property_value` (`id`) ON DELETE CASCADE 

Quindi, cosa ho sbagliato qui? Come è possibile?

risposta

8

Dal manuale:

deviazione dagli standard SQL: Un vincolo FOREIGN KEY che fa riferimento una chiave non univoca non è SQL standard. È un'estensione InnoDB dello standard SQL.

Quindi sembra che InnoDB consenta indici non univoci come candidati per riferimenti di chiavi esterne. Altrove il manuale afferma che è possibile fare riferimento a un sottoinsieme di colonne nell'indice di riferimento purché le colonne di riferimento siano elencate per prime e nello stesso ordine della chiave primaria.

Pertanto, questa definizione è legale in InnoDB, anche se non è SQL standard e mi lascia, almeno, un po 'confuso sulle intenzioni del progettista originale.

Manual page here.

+0

Se vedi questa pagina: http://dev.mysql.com/doc/refman/5.0/en/innodb-foreign- key-constraints.html, il primo punto elenco indica che le chiavi esterne devono fare riferimento a un indice che ha le colonne utilizzate prima dall'elenco di indici e nello stesso ordine specificato dal vincolo. –

-1

Questo è perfettamente legale secondo wikipedia:

Le colonne della tabella di riferimento deve essere la chiave primaria o altro tasto candidata nella tabella con i riferimenti.

+1

La chiave non candidata è la chiave univoca? Oppure stai dicendo che una relazione molti-a-molti può essere modellata con una singola chiave esterna?Sono confuso :( –

+0

In questo caso, le colonne nella tabella di riferimento non sono affatto una chiave (ma piuttosto parte di una chiave più grande) .InnoDB sembra infatti consentirlo, ma non è SQL standard –

+1

Non vedo come la referenziazione di una chiave non univoca sia consentita dalla definizione wiki di chiave esterna o chiave candidata. –

-1

La risposta più probabile è che id è davvero unico nella tabella catalog_propery_value, ma che l'autore ha dichiarato il PK di essere il superchiave (id, sorta) per ragioni sconosciute, forse a che fare con l'indicizzazione, piuttosto che rafforzando l'unicità.

+0

Ho appena controllato, È * NON * unico ... –

+0

Come può il motore SAPERE che l'ID è unico ? È dichiarato o no, e in questo caso chiaramente non è dichiarato univoco. –

2

Questo strano comportamento di FK in innoDB è descritto nello manual.

La gestione dei riferimenti chiave esterna chiavi univoci o chiavi che contengono valori NULL non è ben definito per operazioni come UPDATE o DELETE CASCADE. Si consiglia di utilizzare chiavi esterne che fanno riferimento solo a chiavi UNICHE e NON NULL.

PostgreSQL non accetta questa costruzione, la chiave esterna deve puntare a una chiave univoca.

Problemi correlati