是否可以使用复合外键作为表的复合主键的一部分?
例如,假设我有两张桌子:
CREATE TABLE DB.dbo.Partners
(
CONSTRAINT pk_Partners_Id
PRIMARY KEY (Name, City, State, Country, PostalCode),
Name VARCHAR(100) NOT NULL,
Address1 VARCHAR(100),
Address2 VARCHAR(100),
Address3 VARCHAR(100),
City VARCHAR(150) NOT NULL,
State CHAR(2) NOT NULL,
Country CHAR(2) NOT NULL,
PostalCode VARCHAR(16) NOT NULL,
Phone VARCHAR(20),
Fax VARCHAR(20),
Email VARCHAR(256)
)
...然后在第二个表中,我想引用第二个表的主键中的外键:
CREATE TABLE DB.dbo.PartnerContacts
(
CONSTRAINT pk_PartnerContacts_Id
PRIMARY KEY (fk_PartnerContacts_PartnerId, FirstName, LastName, PhoneNumber, Email),
CONSTRAINT fk_PartnerContacts_PartnerId
FOREIGN KEY REFERENCES Partners(Name, City, State, Country, PostalCode),
FirstName VARCHAR(75) NOT NULL,
MiddleName VARCHAR(75),
LastName VARCHAR(75) NOT NULL,
PhoneNumber VARCHAR(20) NOT NULL,
MobileNumber VARCHAR(20),
FaxNumber VARCHAR(20),
Email VARCHAR(256) NOT NULL,
MailTo VARCHAR(100),
Address1 VARCHAR(100),
Address2 VARCHAR(100),
Address3 VARCHAR(100),
City VARCHAR(150),
State CHAR(2),
Country CHAR(2),
PostalCode VARCHAR(16)
)
有什么办法可以做到这一点吗? 是的,在这些表中简单地使用 IDENTITY 列可能会更容易,但如果我可以在没有 IDENTITY 的情况下定义实际关系,我想这样做。
编辑:
我想提供最终的、有效的 SQL。 感谢所有回答的人!
CREATE TABLE DB.dbo.Partners
(
CONSTRAINT pk_Partners_Id
PRIMARY KEY (Name, City, State, Country, PostalCode),
Id INT NOT NULL UNIQUE IDENTITY(1, 1),
Name VARCHAR(100) NOT NULL,
Address1 VARCHAR(100),
Address2 VARCHAR(100),
Address3 VARCHAR(100),
City VARCHAR(150) NOT NULL,
State CHAR(2) NOT NULL,
Country CHAR(2) NOT NULL,
PostalCode VARCHAR(16) NOT NULL,
Phone VARCHAR(20),
Fax VARCHAR(20),
Email VARCHAR(256)
)
CREATE TABLE DB.dbo.PartnerContacts
(
CONSTRAINT pk_PartnerContacts_Id
PRIMARY KEY
(PartnerId, FirstName, LastName, PhoneNumber, Email),
PartnerId INT NOT NULL CONSTRAINT fk_PartnerContacts_PartnerId FOREIGN KEY REFERENCES Partners(Id),
FirstName VARCHAR(75) NOT NULL,
MiddleName VARCHAR(75),
LastName VARCHAR(75) NOT NULL,
PhoneNumber VARCHAR(20) NOT NULL,
MobileNumber VARCHAR(20),
FaxNumber VARCHAR(20),
Email VARCHAR(256) NOT NULL,
MailTo VARCHAR(100),
Address1 VARCHAR(100),
Address2 VARCHAR(100),
Address3 VARCHAR(100),
City VARCHAR(150),
State CHAR(2),
Country CHAR(2),
PostalCode VARCHAR(16)
)
您可能需要指定应该匹配的列。
CONSTRAINT fk_PartnerContacts_PartnerId
FOREIGN KEY (columns that correspond to referenced columns)
REFERENCES Partners (Name, City, State, Country, PostalCode),
因此,您需要提供五个列名称,其值应与“Partners”表中的 {Name, City, State, Country, PostalCode} 的值匹配。 我很确定你目前的结构无法做到这一点。您将无法匹配“姓名”。我认为您正在寻找类似的东西。
CREATE TABLE DB.dbo.PartnerContacts (
-- Start with columns that identify "Partner".
partner_name VARCHAR(100) NOT NULL,
partner_city VARCHAR(150) NOT NULL,
partner_state CHAR(2) NOT NULL,
partner_country CHAR(2) NOT NULL,
partner_postcode VARCHAR(16) NOT NULL,
CONSTRAINT fk_PartnerContacts_PartnerId
FOREIGN KEY (partner_name, partner_city, partner_state, partner_country, partner_postcode)
REFERENCES Partners (Name, City, State, Country, PostalCode),
FirstName VARCHAR(75) NOT NULL,
MiddleName VARCHAR(75),
LastName VARCHAR(75) NOT NULL,
PhoneNumber VARCHAR(20) NOT NULL,
MobileNumber VARCHAR(20),
FaxNumber VARCHAR(20),
Email VARCHAR(256) NOT NULL,
MailTo VARCHAR(100),
Address1 VARCHAR(100),
Address2 VARCHAR(100),
Address3 VARCHAR(100),
City VARCHAR(150),
State CHAR(2),
Country CHAR(2),
PostalCode VARCHAR(16),
CONSTRAINT pk_PartnerContacts_Id
PRIMARY KEY (partner_name, partner_city, partner_state, partner_country, partner_postcode,
FirstName, LastName, PhoneNumber, Email)
);
是的,这是可能的,并且通常被认为是最佳的数据库设计实践,但实际上,ID 列更容易处理。想想连接表,它们的主键是两个外键的组合。使用多个外键作为复合主键的一部分没有区别。
是的,这绝对是可能的。我们确实有这样的情况:我们有一个复合外键,它是其他表的复合主键的一部分。
让我们稍微简化一下下面示例的用例。
假设我们有一个表 test1,它具有复合主键 (A, B)
现在我们可以有一个表 test2 具有主键(P,Q,R),其中 test2 的(P,Q)引用 test1 的(A,B)。
我在 MySql 数据库中运行了以下脚本,它运行得很好。
CREATE TABLE `test1` (
`A` INT NOT NULL,
`B` VARCHAR(2) NOT NULL,
`C` DATETIME NULL,
`D` VARCHAR(45) NULL,
PRIMARY KEY (`A`, `B`));
CREATE TABLE `test2` (
`P` INT NOT NULL,
`Q` VARCHAR(2) NOT NULL,
`R` INT NOT NULL,
`S` DATETIME NULL,
`T` VARCHAR(8) NULL,
PRIMARY KEY (`P`, `Q`, `R`),
INDEX `PQ_idx` (`P`,`Q` ASC),
CONSTRAINT `PQ`
FOREIGN KEY (`P`, `Q`)
REFERENCES `test1` (`A`,`B`)
ON DELETE CASCADE
ON UPDATE CASCADE);
在上述情况下,数据库期望 (A,B) 的组合是唯一的,并且它确实是 test1 表中的主键。
但如果您尝试执行以下操作,脚本将会失败。数据库不允许您创建 test2 表。
CREATE TABLE `test2` (
`P` INT NOT NULL,
`Q` VARCHAR(2) NULL,
`R` DATETIME NULL,
`S` VARCHAR(8) NULL,
`T` VARCHAR(45) NULL,
INDEX `P_idx` (`P` ASC),
INDEX `Q_idx` (`Q` ASC),
CONSTRAINT `P`
FOREIGN KEY (`P`)
REFERENCES `test1` (`A`)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT `Q`
FOREIGN KEY (`Q`)
REFERENCES `test1` (`B`)
ON DELETE CASCADE
ON UPDATE CASCADE);
在上述案例中,数据库期望 A 列单独唯一,B 列也同样如此。(A,B) 的组合是否唯一并不重要。