[英]Compound primary key issue with foreign key
I'm getting this error:我收到此错误:
There are no primary or candidate keys in referenced table 'User' that match.
引用的表“用户”中没有匹配的主键或候选键。
I checked for other similar questions but different answers didn't help me.我检查了其他类似的问题,但不同的答案对我没有帮助。
Are my primary keys set wrong?我的主键设置错了吗?
Must I reference only one primary key in ShoppingCart
table ?我必须在
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)
)
Thank you very much for all the users who answer me below.非常感谢所有在下面回答我的用户。
As I have mentioned in the comments, the problem is that you are trying to create a FOREIGN KEY
that references a PRIMARY KEY
/ UNIQUE CONSTRAINT
in your table User
which is made up of UserID
and only UserID
;正如我在评论中提到的,问题是您正在尝试创建一个
FOREIGN KEY
来引用您的表User
的PRIMARY KEY
/ UNIQUE CONSTRAINT
,它由UserID
和只有UserID
; no such constraint exists and as such the creation of the FOREIGN KEY
fails.不存在这样的约束,因此创建
FOREIGN KEY
失败。
To address this literally, you would need to add the EmailAddress
column to the ShoppingCart
table and the FOREIGN KEY
's definition:为了从字面上解决这个问题,您需要将
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)
)
This, in truth, is a bad idea, as what do you think would happen if someone changed their email address?事实上,这是一个坏主意,因为如果有人更改了他们的电子邮件地址,您认为会发生什么? Well, let's try.
好吧,让我们试试。 Firstly, let's create some sample data:
首先,让我们创建一些示例数据:
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());
And now Let's say Jane has changed her Email address, so we try to UPDATE
the table:现在假设 Jane 更改了她的电子邮件地址,因此我们尝试
UPDATE
表:
UPDATE dbo.[User]
SET EmailAddress = N'Jane.Bloggs@email.com'
WHERE UserId = 1;
The INSERT statement conflicted with the FOREIGN KEY constraint "FK__ShoppingCart__36DDA17A".
INSERT 语句与 FOREIGN KEY 约束“FK__ShoppingCart__36DDA17A”冲突。 The conflict occurred in database "Sandbox", table "dbo.User".
冲突发生在数据库“Sandbox”、表“dbo.User”中。
This is because the value of EmailAddress
in the table ShoppingCart
is still N'Jane@bloggs.com'
, so the value can't be updated.这是因为表
ShoppingCart
中EmailAddress
的值仍然是N'Jane@bloggs.com'
,所以该值无法更新。 Obviously, you can't also UPDATE
the value in dbo.ShopppingCart
because you'll get the same error:显然,你也不能
UPDATE
dbo.ShopppingCart
的值,因为你会得到同样的错误:
UPDATE dbo.[ShoppingCart]
SET EmailAddress = N'Jane.Bloggs@email.com'
WHERE UserId = 1;
The INSERT statement conflicted with the FOREIGN KEY constraint "FK__ShoppingCart__415B2FED".
INSERT 语句与 FOREIGN KEY 约束“FK__ShoppingCart__415B2FED”冲突。 The conflict occurred in database "Sandbox", table "dbo.User".
冲突发生在数据库“Sandbox”、表“dbo.User”中。
So what do you do instead?那么你会怎么做呢? Well I assume that the email address is meant to be unique within the application, not by user.
好吧,我假设电子邮件地址在应用程序中是唯一的,而不是用户。 At the moment you could have 100 Users with a
UserID
of 1
and provided they all had different Email Addresses, they would be valid Primary Keys.目前,您可以拥有 100 个用户
UserID
为1
的UserID
,并且如果他们都有不同的电子邮件地址,则它们将是有效的主键。 Most likely what you really want, based on that you don't want EmailAddress
in the table ShoppingCard
, is for UserID
to be the Primary Key, and the Email Address to have a separate Unique Constraint.很可能您真正想要的是,基于您不希望表
ShoppingCard
EmailAddress
是UserID
作为主键,并且电子邮件地址具有单独的唯一约束。 This gives you the following instead:这将为您提供以下内容:
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);
I also give your constraints explicit names, a habit you should really get into.我还为您的约束提供了明确的名称,这是您应该真正养成的习惯。
Now you can INSERT
the sample data, and UPDATE
the email address without issue:现在您可以
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;
And if you try to add another user with the same email address, you get an error:如果您尝试添加具有相同电子邮件地址的其他用户,则会收到错误消息:
INSERT INTO dbo.[User] (EmailAddress, FirstName, LastName)
VALUES(N'Jane.Bloggs@email.com','Jane','Bloggs');
Violation of UNIQUE KEY constraint 'UQ_UserEmail'.
违反 UNIQUE KEY 约束“UQ_UserEmail”。 Cannot insert duplicate key in object 'dbo.User'.
无法在对象“dbo.User”中插入重复键。 The duplicate key value is (Jane.Bloggs@email.com).
重复的键值为 (Jane.Bloggs@email.com)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.