How to use two columns in a foreign key constraint - sql

I have two tables:
Article
Subscription
In the Article table I have two columns that make up the primary key: id, sl. In the Subscription table I have a foreign key 'idsl`.
I use this constraint :
constraint FK_idsl
foreign key (idsl) references CSS_SubscriptionGroup(id, sl)
But when I run the query, I getting this error:
Number of referencing columns in foreign key differs from number of referenced columns, table X

In Article Table I have two fields that are the primary key: id,sl. In the Subscription Table I have a foreign key 'idsl`
This design is broken - it is apparent that the composite primary key in Article(id, sl) has been mangled into a single compound foreign key in table Subscription. This isn't a good idea.
Instead, you will need to change the design of table Subscription to include separate columns for both id and sl, of the same type as the Article Table, and then create a composite foreign key consisting of both columns, referencing Article in the same order as the primary key, e.g:
CREATE TABLE Article
(
id INT NOT NULL,
sl VARCHAR(50) NOT NULL,
-- Other Columns
CONSTRAINT PK_Article PRIMARY KEY(id, sl) -- composite primary key
);
CREATE TABLE Subscription
(
-- Other columns
id INT NOT NULL, -- Same type as Article.id
sl VARCHAR(50) NOT NULL, -- Same type as Article.sl
CONSTRAINT FK_Subscription_Article FOREIGN KEY(id, sl)
REFERENCES Article(id, sl) -- Same order as Article PK
);
Edit
One thing to consider here is that by convention a column named table.id or table.tableid should be unique, and is the primary key for the table. However, since table Article requires an additional column sl in the primary key, it implies that id isn't unique.

correct syntax for relation:
CONSTRAINT FK_OtherTable_ParentTable
FOREIGN KEY(OrderId, CompanyId) REFERENCES dbo.ParentTable(OrderId, CompanyId)
You must try like this:
constraint FK_idsl foreign key (id,sl) references CSS_SubscriptionGroup(id,sl)

Related

SQL table stopping me from adding foreign key

I'm creating a SQL table in VS that stores what rooms each client is, So the table has RoomId (int) and UserID (int).
Because I only want to add to the table only rooms and clients that exist they are both keys that have a foreign key to 2 tables, one that stores RoomID and Name and another that stores Client ID and Name.
Room and UserId tables:
CREATE TABLE [dbo].[UsersInRoomsTable]
(
RoomId INT NOT NULL,
UserId INT NOT NULL,
CONSTRAINT PK_RS PRIMARY KEY(RoomId, UserId),
CONSTRAINT [fk_room] FOREIGN KEY([RoomId]) REFERENCES [dbo].[RoomsTable]([RoomId]),
CONSTRAINT [fk_user] FOREIGN KEY ([UserId]) REFERENCES [dbo].[UserInfoTable] ([UserId])
);
Table that stores all the users:
CREATE TABLE [dbo].[UserInfoTable]
(
[UserName] NVARCHAR (50) NOT NULL,
[UserId] INT NOT NULL,
CONSTRAINT [PK_roomuser] PRIMARY KEY CLUSTERED ([UserName] ASC, [UserId] ASC)
);
Table that stores all the rooms
CREATE TABLE [dbo].[RoomsTable]
(
[RoomId] INT NOT NULL,
[RoomName] NVARCHAR (50) NOT NULL,
PRIMARY KEY CLUSTERED ([RoomId] ASC)
);
Everything works except the last line in the Rooms and users table:
CONSTRAINT [fk_user] FOREIGN KEY ([UserId]) REFERENCES [dbo].[UserInfoTable] ([UserId])
When I try to Update the table I get an error SQL71516:
SQL71516: The referenced table '[dbo].[UserInfoTable]' contains no primary or candidate keys that match the referencing column list in the foreign key.
If the referenced column is a computed column, it should be persisted
How can I solve this problem and what is causing it?
Edit: I think I know what is code is colliding: For some reason I can not have a foreign key connecting to a key that contains 2 indexes IE: fk_user is a Fk to table UserInfoTable that has 2 keys (UserID and UserName)
is there a way to pass this obstacle?
The columns of a foreign key have to match the columns they reference by number, type and order.
You have a primary key on userinfotable of (username, userid). But in usersinroomstable you are trying to let the foreign key (userid) to reference that. The number of columns doesn't match, so the foreign key cannot be added.
Presumably the username shouldn't really be part of the primary key of userinfotable and got there by accident. Remove it from the primary key constraint.
Or, if username has to be in the primary key, add such a column to the table usersinroomstable and add it to the foreign key constraint.

Why is my create table failing? - does not match primary key

This is what I am trying to create:
CREATE TABLE VEHICLEREPORT
(
DeptID char(2) not null,
Vin# char(3) not null,
Miles varchar(6) not null,
Bill# char(3) not null,
EID char(3) not null,
PRIMARY KEY (DeptID, Vin#),
FOREIGN KEY (bill#) REFERENCES billing,
FOREIGN KEY (EID) REFERENCES Employee
);
The issue is with my reference to billing. The error says:
The number of columns in the referencing column list for foreign key 'FK__VEHICLERE__Bill#__5AEE82B9' does not match those of the primary key in the referenced table 'Billing'.
but my billing table entered fine:
CREATE TABLE BILLING
(
VIN# char(3),
BILL# char(3),
PRIMARY KEY (VIN#, Bill#),
FOREIGN KEY (VIN#) REFERENCES vehicle
);
What am i missing with this?
Appreciate the help.
If you think of the foreign key as establishing a parent-child relationship between two tables, then the parent side column(s) need to be unique.
From Wikipedia:
In the context of relational databases, a foreign key is a field (or collection of fields) in one table that uniquely identifies a row of another table or the same table. ... In simpler words, the foreign key is defined in a second table, but it refers to the primary key or a unique key in the first table.
In your example, there is no guarantee that VIN# is unique in VEHICLEREPORT. Below are your options
VIN# is guaranteed to be unique in VEHICLEREPORT. In this case add a UNIQUE constraint on VIN# on the VEHICLEREPORT table. The error will go away.
VIN# is not unique in VEHICLEREPORT (doesn't seem likely). If this is the case, then likely there is a flaw in the design of your BILLING table as it could likely point to more than one row in VEHICLEREPORT. You should consider adding DeptID column to BILLING and creating a composite foreign key.
Also if VIN# is unique (case 1 above), you should think of why DeptID is present in the PK. Maybe the right fix at the end is to drop DeptID from the primary key.

Required to Declare Primary Keys on Junction Table?

In a junction table made up of only foreign keys (e.g. ShopSupplier in the example below), must we also declare those columns as primary keys in the DDL create statement? If yes, what would be the point of doing so? I would argue that these are NOT primary keys in the example below
CREATE TABLE Shop
(
ShopID TEXT PRIMARY KEY UNIQUE,
ShopName TEXT
);
CREATE TABLE Supplier
(
SupplierID TEXT PRIMARY KEY UNIQUE,
SupplierName TEXT
);
CREATE TABLE ShopSupplier
(
ShopID TEXT,
SupplierID TEXT,
FOREIGN KEY(ShopID) REFERENCES Shop(ShopID),
FOREIGN KEY(SupplierID) REFERENCES Supplier(SupplierID)
);
The question again: Should I also declare PRIMARY KEY(ShopID, SupplierID) for the ShopSupplier table. If so, why? I would argue that there should be no primary key for that table.
Both columns are foreign key, because they are referencing to other tables. In the case that only single connection between specific rows of Shopand Supplier may exit, you can use a unique constraint or create a combined primary key:
CREATE TABLE ShopSupplier(
ShopID TEXT,
SupplierID TEXT,
PRIMARY KEY(ShopID, SupplierID),
FOREIGN KEY(ShopID) REFERENCES Shop(ShopID),
FOREIGN KEY(SupplierID) REFERENCES Supplier(SupplierID));
Then, both columns are foreign keys and belonging to the primary key.
In general setting the columns of a (pure) junction table as primary key isn't necessary. You may use it as a constraint to prohibit duplicates.

There are no PK in the referenced table. Why?

I have the following T-SQL to create 3 SQL tables:
create table dbo.Posts
(
Id int identity not null
constraint PK_Posts_Id primary key clustered (Id),
Active bit not null
constraint DF_Posts_Active default (0)
);
create table dbo.PostsLocalized
(
Id int not null,
Culture int not null
constraint CK_PostsLocalized_Culture check ([Culture] in ('1', '2', '3')),
[Text] nvarchar (200) not null,
constraint PK_PostsLocalized_Id_Culture primary key clustered (Id, Culture)
);
create table dbo.Tags
(
Id int identity not null
constraint PK_Tags_Id primary key clustered (Id),
Name nvarchar not null
);
create table dbo.PostsLocalized_Tags
(
PostLocalizedId int not null,
TagId int not null,
constraint PK_PostsLocalized_Tags_Post_PostLocalizedId_TagId primary key clustered (PostLocalizedId, TagId)
);
Then I have added the following constraints:
alter table dbo.PostsLocalized
add constraint FK_PostsLocalized_Id foreign key (Id) references dbo.Posts(Id) on delete cascade on update cascade;
alter table dbo.PostsLocalized_Tags
add constraint FK_PostsLocalized_Tags_PostLocalizedId foreign key (PostLocalizedId) references PostsLocalized(Id) on delete cascade on update cascade,
constraint FK_PostsLocalized_Tags_TagId foreign key (TagId) references Tags(Id) on delete cascade on update cascade;
But I get the following error:
There are no primary or candidate keys in the referenced table 'PostsLocalized' that match the referencing column list in the foreign key 'FK_PostsLocalized_Tags_PostLocalizedId'.
How can I solve this?
Thank You,
Miguel
SQL Server mandates that foreign key references be to a primary key or unique key. The foreign key reference has to be to all the columns that constitute the primary/unique key. The documentation says:
In a foreign key reference, a link is created between two tables when
the column or columns that hold the primary key value for one table
are referenced by the column or columns in another table. This column
becomes a foreign key in the second table.
A FOREIGN KEY constraint does not have to be linked only to a PRIMARY
KEY constraint in another table; it can also be defined to reference
the columns of a UNIQUE constraint in another table. A FOREIGN KEY
constraint can contain null values; however, if any column of a
composite FOREIGN KEY constraint contains null values, verification of
all values that make up the FOREIGN KEY constraint is skipped. To make
sure that all values of a composite FOREIGN KEY constraint are
verified, specify NOT NULL on all the participating columns.
The primary key in PostsLocalized contains the culture column, so you need to add it into the foreign key reference.
Your PK on PostsLocalized table is complex consisting of two columns - id and culture and you are trying to create FK on only one of those columns which is not possible.
You'll have to either add Culture column on PostsLocalized_Tags and use them both in foreign key or remove Culture from your PK on PostLocalized

SQL Table Foreign Key that is part of a Composite Primary Key

Is it possible to have a table's foreign key be part of another table's composite primary key?
For example, if I have two tables, one contains information on all active projects of different users and another containing information on what equipment is being used by the projects:
Project Table:
Composite Primary Keys: UserId, ProjectId (neither are unique by themselves)
Equipment Table:
Composite Primary Keys: UserId, ProjectId, EquipmentId (neither are unique by themselves)
Now is it possible to set the ProjectId in the equipment table to be a foreign key from the project table? When I try, I get an error saying that the column in Project Table do not match an existing primary key or unique constraint?
No.
When you create a foreign key, the key that you "point to" in the other table must be a UNIQUE or PRIMARY KEY constraint. You cannot establish a foreign key that points to a column that allow duplicate values. It would be very hard to imagine how the data should "act" if you update one of the duplicate values in the other table (for instance).
To do what you want you must establish a Projects table in which ProjectID is UNIQUE or a PRIMARY KEY and then point foreign keys in both the other tables to that table.
Parenthetically, you use the term "Primary Keys" to describe the columns in each table that make up the primary key. In fact, each table can have one and only one primary key. That key can be composed of one or more columns, but the key itself is still referred to in the singular. This is an important difference when using the primary key to optimize searches.
It do not know if that's a good design practice but for sure it is possible to have a composite foreign key of one table that is the part of the composite primary key of other table.
Say we have a table test1 having a composite primary key (A, B)
Now we can have a table say test2 having primary key (P, Q, R) where in (P,Q) of test2 referencing (A,B) of test2.
I ran the following script in the MySql database and it works just fine.
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);
In the above mentioned case, the database is expecting the combination of (A,B) to be unique and it is, being a primary key in test1 table.
But if you try to do something like following, the script would fail. The database would not let you create the test2 table.
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);
In the above mentioned case database would expect the column A to be unique individually and the same follows for column B. It does not matter if combination of (A,B) is unique.
#Larry Lustig
The foreign key can be part of primary key in the other table.
source: Dependent relationship
Check relationship between tables: Zdarzenie(Event) and TypZdarzenia (type of event)