0

我正在尝试创建一个数据库,并且我的一个表使用复合主键。这工作正常,直到我尝试使用第二个复合键为单独的表创建外键。给出的错误是“ERROR 1005 (HY000): Can't create table '.kesharaproducts\production.frm' (errno: 150)”

这是代码。

create table stocks(
rawMatBatchID VARCHAR(4) NOT NULL,
finishedGoodsBatchID VARCHAR(4) NOT NULL,
rawMaterialID VARCHAR(4) NOT NULL,
finishedMaterialID VARCHAR(4) NOT NULL,
supplierID VARCHAR(5) NOT NULL,
rawMaterialType VARCHAR(10) NOT NULL,
finishedMaterialType VARCHAR(10) NOT NULL,
rawMatWeight VARCHAR(5) NOT NULL,
finishedGoodsWeightKg INT(5) NOT NULL,
finishedGoodsWeightG INT(5) NOT NULL,
finishedGoodsUnits INT(5) NOT NULL,
finishedGoodsDate VARCHAR(15) NOT NULL,
rawMatDate VARCHAR(15) NOT NULL,
PRIMARY KEY (finishedGoodsBatchID, rawMatBatchID),
CONSTRAINT FOREIGN KEY (finishedMaterialID) REFERENCES finishedMaterials(finishedMaterialID),
CONSTRAINT FOREIGN KEY (supplierID) REFERENCES supplierDetails(supplierID),
CONSTRAINT FOREIGN KEY (rawMaterialID) REFERENCES rawMaterials(rawMaterialID))ENGINE=INNODB;

上表使用复合主键。

create table transport(
transportID VARCHAR(4) NOT NULL,
vehicleID VARCHAR(4) NOT NULL,
finishedGoodsBatchID VARCHAR(4) NOT NULL,
finishedGoodsUnits INT(5) NOT NULL,
finishedGoodsWeightKg INT(5),
finishedGoodsWeightG INT(5),
transportDate VARCHAR(15),
CONSTRAINT PRIMARY KEY (transportID),
CONSTRAINT FOREIGN KEY (vehicleID) REFERENCES vehicles(vehicleID),
CONSTRAINT FOREIGN KEY (finishedGoodsBatchID) REFERENCES stocks(finishedGoodsBatchID)
)ENGINE=INNODB;

上表使用了第一个复合键并且工作正常。

create table production(
productionBatchID VARCHAR(4) NOT NULL,
finishedMaterialID VARCHAR(4) NOT NULL,
rawMaterialID VARCHAR(4) NOT NULL,
productionDate VARCHAR(15),
rawMatBatchID VARCHAR(4),
initialWeight INT(5),
beforeWeight INT(5),
afterWeight INT(5),
finalWeight INT(5),
packingWeight INT(5),
noOfUnits INT(5),
wastage INT(5),
CONSTRAINT PRIMARY KEY (productionBatchID),
CONSTRAINT FOREIGN KEY (finishedMaterialID) REFERENCES finishedMaterials(finishedMaterialID),
CONSTRAINT FOREIGN KEY (rawMaterialID) REFERENCES rawMaterials(rawMaterialID),
CONSTRAINT FOREIGN KEY (rawMatBatchID) REFERENCES stocks(rawMatBatchID))ENGINE=INNODB;

但是在上表中,它使用第二个复合主作为外键,它给出了错误。如何解决这个问题?这是最后三个表。创建所有其他引用的表。我没有在这里发布所有表格,太长了。当我从最后一个表中删除“CONSTRAINT FOREIGN KEY (rawMatBatchID) REFERENCES stock(rawMatBatchID)”并添加它被添加的表时。但不是对第二个复合键的引用......

4

3 回答 3

1

外键应具有与其引用的主键相同的列对。

您的transport表工作的原因是 InnoDB 支持对 SQL 的一个有趣的非标准扩展,以便外键可以引用复合键中的一列,但前提是它引用了列的左子集

您的production表仅引用了所引用主键中的第二列,并且不能以这种方式工作。

我不确定你想用这个设计做什么。尽管 InnoDB 能够对列的子集进行引用,但这是非标准 SQL,不推荐使用。

最好将主键中的列都添加到引用它的两个表中,并制作复合外键来引用复合主键。stocks

于 2013-05-19T19:48:31.933 回答
1

stocks 没有 2 个主键。它只有一个。它是一个复合键,由 2 个部分组成:(finishedGoodsBatchID, rawMatBatchID).

如果您希望有FOREIGN KEY引用表的约束,您应该引用该表的主键(或唯一键)。它的全部。所以,在这种情况下,整个复合主键stocks不是它的一部分。

这也使得外键不会transport出错。MySQL 允许它,但如果你这样离开它,你会遇到问题。外键应该能够以某种方式识别父表中的行,但(finishedGoodsBatchID)不能单独(识别行)。

所以,transport定义应该是:

CREATE TABLE transport(
    transportID VARCHAR(4) NOT NULL,
    vehicleID VARCHAR(4) NOT NULL,
    finishedGoodsBatchID VARCHAR(4) NOT NULL,
    rawMatBatchID VARCHAR(4) NOT NULL,                            -- added
    finishedGoodsUnits INT(5) NOT NULL,
    finishedGoodsWeightKg INT(5),
    finishedGoodsWeightG INT(5),
    transportDate VARCHAR(15),
    CONSTRAINT 
      PRIMARY KEY (transportID),
    CONSTRAINT 
      FOREIGN KEY (vehicleID) 
      REFERENCES vehicles(vehicleID),
    CONSTRAINT                                                    -- changed
      FOREIGN KEY (finishedGoodsBatchID, rawMatBatchID) 
      REFERENCES stocks (finishedGoodsBatchID, rawMatBatchID)
) ENGINE=INNODB;

在表的定义中也应该进行类似的更改production

于 2013-05-19T19:49:06.950 回答
-1

您正在引用尚不存在的表。禁用外键,创建表,然后重新启用外键。

SET foreign_key_checks = 0;

创建表...

SET foreign_key_checks = 1;
于 2013-05-19T19:30:02.557 回答