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 ?
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.
Advertisement
Answer
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
; no such constraint exists and as such the creation of the FOREIGN KEY
fails.
To address this literally, you would need to add the EmailAddress
column to the ShoppingCart
table and the FOREIGN KEY
‘s definition:
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:
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”. The conflict occurred in database “Sandbox”, table “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. Obviously, you can’t also UPDATE
the value in dbo.ShopppingCart
because you’ll get the same error:
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”. The conflict occurred in database “Sandbox”, table “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. 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. 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 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’. Cannot insert duplicate key in object ‘dbo.User’. The duplicate key value is (Jane.Bloggs@email.com).