2010-03-02 9 views
7

que estaba migrando base de datos MySQL a PostgreSQL y tropezamos con el siguiente bloque en DDL (Nota: Esto es lo que tengo de mysqldump):Clave externa de Mysql por clave no única: ¿cómo es posible?

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; 

Ahora, lo que veo aquí es que la única clave única en el primera tabla es una combinación de (id, más o menos):

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

sin embargo, la segunda tabla tiene una referencia a la primera columna en por ID única, que no es única!

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

Entonces, ¿qué hice mal aquí? ¿Cómo es eso posible?

Respuesta

8

Del manual:

desviación del estándar SQL: Un restricción FOREIGN KEY que hace referencia a una clave no única, no es SQL estándar. Es una extensión InnoDB al estándar SQL.

Parece que InnoDB permite índices no únicos como candidatos para referencias de claves foráneas. En otras partes, el manual establece que puede hacer referencia a un subconjunto de columnas en el índice al que se hace referencia, siempre que las columnas a las que se hace referencia estén enumeradas primero y en el mismo orden que la clave principal.

Por lo tanto, esta definición es legal en InnoDB, aunque no es SQL estándar y me deja, al menos, un poco confundido en cuanto a las intenciones del diseñador original.

Manual page here.

+0

Si ve esta página: http://dev.mysql.com/doc/refman/5.0/en/innodb-foreign- key-constraints.html, el primer punto señala que las claves foráneas deben hacer referencia a un índice que tenga las columnas utilizadas por la lista de índice primero y en el mismo orden que especifica la restricción. –

-1

Esto es perfectamente legal de acuerdo con wikipedia:

Las columnas de la tabla de referencia debe ser la clave primaria u otra clave candidato en la tabla referenciada.

+1

¿No es la clave candidata la clave única? ¿O está diciendo que una relación Muchos a Muchos se puede modelar con una sola clave externa?Estoy confundido :( –

+0

En este caso, las columnas en la tabla de referencia no son ninguna clave (sino más bien parte de una clave más grande). De hecho, InnoDB parece permitir que eso suceda. Pero no es SQL estándar –

+1

No veo cómo es posible hacer referencia a una clave no única mediante la definición wiki de clave externa o clave candidata. –

-1

La respuesta más probable es que ID es realmente único en la tabla catalog_propery_value, pero que el autor declaró el PK ser el superkey (id, más o menos) por razones desconocidas, posiblemente tenga que ver con la indexación, en lugar de imponiendo la unicidad

+0

Acabo de marcar, es * NO * único ... –

+0

¿Cómo podría el motor SABER que la identificación es única? ? Se ha declarado así, o no, y en este caso, claramente no se declara único. –

2

Este extraño comportamiento de FK en innoDB se describe en el manual.

El manejo de referencias de clave externa a las teclas no únicos o claves que contienen valores NULL no es así definido para operaciones tales como ACTUALIZACIÓN o DELETE CASCADE. Se le recomienda que use claves externas que hacen referencia solo a las claves UNIQUE y NOT NULL.

PostgreSQL no acepta esta construcción, la clave foránea tiene que apuntar a una clave única.

Cuestiones relacionadas