我正在将mysql数据库迁移到postgres并在DDL中偶然发现以下块(注意:这是我从mysqldump获得的):
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;
现在,我在这里看到的是第一个表中唯一的唯一键是(id,sort)的组合:
PRIMARY KEY (`id`,`sort`),
但是,第二个表只有id列的第一个on引用,这不是唯一的!
CONSTRAINT `FK_catalog_realty_property_value_link_value` FOREIGN KEY (`value_id`) REFERENCES `catalog_property_value` (`id`) ON DELETE CASCADE
那么,我在这里弄错了什么?怎么可能?
答案 0 :(得分:8)
从手册:
偏离SQL标准:A 引用的FOREIGN KEY约束 非UNIQUE键不是标准SQL。 它是标准的InnoDB扩展 SQL。
所以看起来InnoDB允许非唯一索引作为外键引用的候选者。在其他地方,手册指出您可以引用引用索引中的列子集,只要引用的列首先列出并且与主键的顺序相同。
因此,这个定义在InnoDB中是合法的,虽然它不是标准的SQL,但至少让我对原始设计师的意图感到有些困惑。
答案 1 :(得分:2)
在manual中描述了FK在innoDB中的这种奇怪行为。
处理对非唯一键或键的外键引用 包含NULL值的不太好 为诸如UPDATE之类的操作定义 或DELETE CASCADE。建议你 使用仅引用的外键 UNIQUE和NOT NULL键。
PostgreSQL不接受这种结构,外键必须指向一个唯一的密钥。
答案 2 :(得分:-1)
根据wikipedia:
,这完全合法引用表中的列 必须是主键或其他 引用表中的候选键。
答案 3 :(得分:-1)
最可能的答案是id在catalog_propery_value表中确实是唯一的,但是作者声明PK是超级密钥(id,sort),原因不明,可能与索引有关,而不是强制执行唯一性。