[英]Compound primary key issue with foreign key
我收到此错误:
引用的表“用户”中没有匹配的主键或候选键。
我检查了其他类似的问题,但不同的答案对我没有帮助。
我的主键设置错了吗?
我必须在ShoppingCart
表中只引用一个主键吗?
CREATE TABLE [User]
(
EmailAddress NVARCHAR(320),
UserId INT IDENTITY(1,1),
UserPassword VARCHAR(16),
FirstName VARCHAR(256) NOT NULL,
LastName VARCHAR(256) NOT NULL,
MobileNumber BIGINT,
PRIMARY KEY (EmailAddress, UserId)
)
CREATE TABLE [ShoppingCart]
(
OrderId INT PRIMARY KEY IDENTITY(1,1),
UserId INT FOREIGN KEY REFERENCES [User](UserId), //-- error here
CreatedDate NVARCHAR(40)
)
非常感谢所有在下面回答我的用户。
正如我在评论中提到的,问题是您正在尝试创建一个FOREIGN KEY
来引用您的表User
的PRIMARY KEY
/ UNIQUE CONSTRAINT
,它由UserID
和只有UserID
; 不存在这样的约束,因此创建FOREIGN KEY
失败。
为了从字面上解决这个问题,您需要将EmailAddress
列添加到ShoppingCart
表和FOREIGN KEY
的定义:
CREATE TABLE dbo.[User]
(
EmailAddress NVARCHAR(320),
UserId INT IDENTITY(1,1),
UserPassword VARCHAR(16),
FirstName VARCHAR(256) NOT NULL,
LastName VARCHAR(256) NOT NULL,
MobileNumber varchar(20), --Numerical data types are a poor choice for a Phone Number
PRIMARY KEY (EmailAddress, UserId)
)
CREATE TABLE dbo.[ShoppingCart]
(
OrderId INT PRIMARY KEY IDENTITY(1,1),
UserId INT,
EmailAddress nvarchar(320),
CreatedDate datetime2(0), --(n)varchar is not a "one size fits all" data type.
FOREIGN KEY (EmailAddress,UserID) REFERENCES [User](EmailAddress,UserId)
)
事实上,这是一个坏主意,因为如果有人更改了他们的电子邮件地址,您认为会发生什么? 好吧,让我们试试。 首先,让我们创建一些示例数据:
INSERT INTO dbo.[User] (EmailAddress, FirstName, LastName)
VALUES(N'Jane@bloggs.com','Jane','Bloggs');
INSERT INTO dbo.ShoppingCart (UserId, EmailAddress, CreatedDate)
VALUES(1, N'Jane@bloggs', GETDATE());
现在假设 Jane 更改了她的电子邮件地址,因此我们尝试UPDATE
表:
UPDATE dbo.[User]
SET EmailAddress = N'Jane.Bloggs@email.com'
WHERE UserId = 1;
INSERT 语句与 FOREIGN KEY 约束“FK__ShoppingCart__36DDA17A”冲突。 冲突发生在数据库“Sandbox”、表“dbo.User”中。
这是因为表ShoppingCart
中EmailAddress
的值仍然是N'Jane@bloggs.com'
,所以该值无法更新。 显然,你也不能UPDATE
dbo.ShopppingCart
的值,因为你会得到同样的错误:
UPDATE dbo.[ShoppingCart]
SET EmailAddress = N'Jane.Bloggs@email.com'
WHERE UserId = 1;
INSERT 语句与 FOREIGN KEY 约束“FK__ShoppingCart__415B2FED”冲突。 冲突发生在数据库“Sandbox”、表“dbo.User”中。
那么你会怎么做呢? 好吧,我假设电子邮件地址在应用程序中是唯一的,而不是用户。 目前,您可以拥有 100 个用户UserID
为1
的UserID
,并且如果他们都有不同的电子邮件地址,则它们将是有效的主键。 很可能您真正想要的是,基于您不希望表ShoppingCard
EmailAddress
是UserID
作为主键,并且电子邮件地址具有单独的唯一约束。 这将为您提供以下内容:
CREATE TABLE dbo.[User] -- I recommend against the name USER, it's a reserved keyword
(
EmailAddress NVARCHAR(320),
UserId INT IDENTITY(1,1),
UserPassword VARCHAR(16),
FirstName VARCHAR(256) NOT NULL,
LastName VARCHAR(256) NOT NULL,
MobileNumber varchar(20), --Numerical data types are a poor choice for a Phone Number
);
ALTER TABLE dbo.[User] ADD CONSTRAINT PK_User PRIMARY KEY (UserId);
ALTER TABLE dbo.[User] ADD CONSTRAINT UQ_UserEmail UNIQUE (EmailAddress);
GO
CREATE TABLE dbo.[ShoppingCart]
(
OrderId INT IDENTITY(1,1),
UserId INT,
CreatedDate datetime2(0), --(n)varchar is not a "one size fits all" data type.
)
ALTER TABLE dbo.[ShoppingCart] ADD CONSTRAINT PK_ShoppingCart PRIMARY KEY (OrderId);
ALTER TABLE dbo.[ShoppingCart] ADD CONSTRAINT FK_ShoppingCart_User
FOREIGN KEY (UserId)
REFERENCES dbo.[User] (UserID);
我还为您的约束提供了明确的名称,这是您应该真正养成的习惯。
现在您可以INSERT
示例数据,并毫无问题地UPDATE
电子邮件地址:
INSERT INTO dbo.[User] (EmailAddress, FirstName, LastName)
VALUES(N'Jane@bloggs.com','Jane','Bloggs');
INSERT INTO dbo.ShoppingCart (UserId, CreatedDate)
VALUES(1,GETDATE());
GO
UPDATE dbo.[User]
SET EmailAddress = N'Jane.Bloggs@email.com'
WHERE UserId = 1;
如果您尝试添加具有相同电子邮件地址的其他用户,则会收到错误消息:
INSERT INTO dbo.[User] (EmailAddress, FirstName, LastName)
VALUES(N'Jane.Bloggs@email.com','Jane','Bloggs');
违反 UNIQUE KEY 约束“UQ_UserEmail”。 无法在对象“dbo.User”中插入重复键。 重复的键值为 (Jane.Bloggs@email.com)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.