mysql外键复合主键

时间:2016-03-17 15:11:08

标签: mysql sql

我尝试使用MySQL Server 5.x实现以下功能。

我有一个名为Customer的表,就像这样创建:

CREATE TABLE Customer(
Title VARCHAR(30) NOT NULL, 
Name VARCHAR(100) NOT NULL, 
FirstName VARCHAR(100) NOT NULL, 
Street VARCHAR(300) NOT NULL, 
HouseNumber VARCHAR(30) NOT NULL, 
ZipCode VARCHAR(30) NOT NULL, 
City VARCHAR(100) NOT NULL, 
Telephone VARCHAR(30) NOT NULL, 
EMail VARCHAR(300) NULL, 
CONSTRAINT PK_Customer PRIMARY KEY(Title,Name,FirstName),
INDEX Index_Name(Name));

第二个名为'Order'的表格就是这样创建的:

CREATE TABLE `Order`(
Number BIGINT NOT NULL AUTO_INCREMENT,
Customer VARCHAR(230) NOT NULL,
Issued DATETIME NOT NULL,
PRIMARY KEY(Number),
CONSTRAINT FK_Customer FOREIGN KEY(Customer) 
REFERENCES Customer(PK_Customer));

但是我收到了数字错误:

ERROR 1005 (HY000): Can't create table 'SBZ.Order' (errno: 150)

innodb引擎状态向我显示:

------------------------
LATEST FOREIGN KEY ERROR
------------------------
160317 16:05:29 Error in foreign key constraint of table SBZ/Order:
FOREIGN KEY(Customer) REFERENCES Customer(PK_Customer)):
Cannot resolve column name close to:
))

是否可以使用约束为复合主键创建外键?

任何帮助appriciated。 :)

2 个答案:

答案 0 :(得分:1)

首先,您应该在第一个表中有一个CustomerId列。它应该是自动递增的。所以正确的定义是:

CREATE TABLE Customer (
    CustomerId int auto_increment primary key,
    . . .
    unique (title, firstname, name)
);

然后,您可以创建与CustomerId的正确外键关系:

CustomerId int,
. . .
CONSTRAINT FK_Customer FOREIGN KEY(CustomerId) REFERENCES Customer(CustomerId)

这是“正确的”,因为这样的合成键有几个优点:

  • 外键引用要简单得多。
  • 您可以轻松更改组件(更改外键的一部分需要了解级联约束)。
  • 索引中的整数比字符串更有效。

当然,您可以使用复合主键执行相同操作。您只需要第二个表中的所有三列:

Title VARCHAR(30), 
Name VARCHAR(100), 
FirstName VARCHAR(100), 
CONSTRAINT FK_Customer FOREIGN KEY(Title, Name, Firstname) REFERENCES Customer(Title, Name, Firstname)

答案 1 :(得分:0)

您的子表的外键必须包含与父表的主键相同的列。在你的情况下,它看起来像

CREATE TABLE `Order`(
  Number BIGINT NOT NULL AUTO_INCREMENT,
  Title VARCHAR(30) NOT NULL, 
  Name VARCHAR(100) NOT NULL, 
  FirstName VARCHAR(100) NOT NULL,
  ...
  CONSTRAINT FK_Customer FOREIGN KEY (Title, Name, FirstName)
    REFERENCES Customer (Title, Name, FirstName)
);

请注意,列不必与表中的具有相同的顺序,仅在约束的列列表中。