Foreign key referencing primary key of multiple values - sql

Im using ms sql server. I get this msg when I reference a primary key that is a composite key of 3 values in the foreign key.
"number of referencing columns in foreign key differs from the number of reference columns". The problem lies in second last line of code in member booking. Any ideas? Thanks in advance.
CREATE TABLE room
(
Block CHAR (1),
Lvl INT,
rNum INT,
RmType VARCHAR (15),
Condition VARCHAR (15),
CONSTRAINT room_PK PRIMARY KEY (Block, Lvl, rNum),
)
CREATE TABLE booking
(
BookingID INT,
BStartDate DATE,
BEndDate DATE,
Fee DECIMAL (8,2) NOT NULL CHECK (fee >= 0),
Memberbooking INT NOT NULL,
MemberID INT NOT NULL,
CONSTRAINT booking_pk PRIMARY KEY (BookingID),
CONSTRAINT FK_Booking FOREIGN KEY (Memberbooking) references room (Block, Lvl, rNum),
CONSTRAINT FK_MemberID FOREIGN KEY (MemberID) references member (ID)
)

You are getting an error because you are trying to map 1 column (FOREIGN KEY (Memberbooking)) with 3 columns room (Block, Lvl, rNum)
it's possible to create a foreign key relationship to a compound (more
than one column) primary key, make sure to specify the same number of columns in your FOREIGN KEY

You define this constraint in the table booking:
CONSTRAINT FK_Booking FOREIGN KEY (Memberbooking) references room (Block, Lvl, rNum)
meaning that you want the column Memberbooking to reference 3 columns (!!) in the table room.
Each column from a table can reference one column from another table, not multiple ones.
You can define the same column to reference more than 1 columns in another table, but with different constraints, and always 1 to 1.
Read more here: Create Foreign Key Relationships

Since I see from the comments you are intent to implement this type of check, I would propose a check constraint:
CONSTRAINT CK_MemberID CHECK (EXISTS(SELECT 1 FROM room where Memberbooking=room.Block+convert(nchar,room.Lvl)+convert(nchar,room.rNum)))
However, this design is not very good. The lack of seperators in the Membermooking field might cause collisions.
Eg, consider you have a Memberbooking: 'A1101'
Is that Block A, Lvl 11, rNum 01? Or is it Block A, Lvl 1, rNum 101?

On table "room", you currently have a compound natural key. This is a valid design decision. The alternative would be to add a single column artificial id, such as an int Identity. That would lead to two keys on the same table (one of them Primary Key, the other one Unique constraint).
In a foreign key constraint, you can reference any Unique constraint or Primary Key. If you want to keep the "room" table the way it is, then you need to mirror those key fields in the referencing table. So that would mean your "booking" table would need a Block char(1), Lvl int and rNum int column.
That is why an artificial key (on room) can be useful, because then your foreign key constraint (on booking) can be single column and reference that Unique constaint.

Related

There are no primary or candidate keys in the referenced table ' ' that match the referencing column list in the foreign key

Okay so I googled and found an endless amount of results obviously, but none of them were helpful.
The error seem to be self explanatory... but I don't see what I'm doing wrong in this case:
CREATE TABLE Contrat
(ID_contrat int identity(1,1),
ID_client int,
code_contrat int,
date_début date,
date_fin date,
status_contrat varchar(20),
Totalité int,
montant_mensuel int,
CONSTRAINT PK_composed2 primary key(ID_contrat,ID_client,code_contrat),
CONSTRAINT FK_3 foreign key(code_contrat) references type_contract(code_type_contract) ON DELETE CASCADE,
CONSTRAINT FK_4 foreign key(ID_Client) references Clients(ID_Client) ON DELETE CASCADE
)
CREATE TABLE FonctionContract
(ID_FonctionContract int identity(1,1),
ID_contract int,
ID_fonction int,
nombre int,
prix_unitaire numeric(16,2),
Constraint PK_composed primary key(ID_fonctionContract, ID_Contract, ID_Fonction),
Constraint FK_11 foreign key(ID_contract) references Contrat(ID_contrat) ON DELETE CASCADE,
Constraint FK_2 foreign key(ID_Fonction) references Fonction(ID_fonction) ON DELETE CASCADE
)
The error is occuring in the before last line (FK_11).
Some results says that I should do a composed foreign key too, but I don't see how when I have ID_FonctionContract not being linked anywhere.
Each value of a Foreign Key constraint needs to reference exactly one row of the target table, and the DBMS needs to be able to guarantee this based on the table definitions.
Although the ID_contrat column is defined as auto-incremented, it is not constrained to be unique, because you've defined a multi-column Primary Key on the Contrat table. So the DBMS is saying that a single ID_contrat in your proposed Foreign Key could potentially match multiple rows in the Contrat table, which is not allowed. (This seems surprising, because you probably know that it will only match one, but the DBMS doesn't!)
You need to do one of two things:
Define your foreign key across multiple columns, so that it matches the multiple columns guaranteed to be unique on the other table; that will require you to have all three columns in the FonctionContrat table (ID_contrat, ID_client, and code_contrat)
Adjust the definition of the Contrat table to say that ID_contrat is in fact unique across all rows, either by changing the Primary Key definition, or adding an additional Unique Constraint on the ID_contrat column
I suspect the second option is the appropriate one here: it's rather unusual to use an auto-increment column and then insert duplicates into it.
What you possibly intended was two different unique constraints / indexes: one on ID_contrat and a separate one on combinations of ID_client and code_contrat. Only one of those can be marked as the Primary Key, but the other can be a Unique Index, which has most of the same functionality in practice; either one can be marked "clustered", which tells SQL Server to physically lay out the table based on that column.

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.

How to use two columns in a foreign key constraint

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)

SQL Server Foreign Key

I'm trying to create this database with the following relations in SQL Server and I get this error:
Msg 1776, Level 16, State 0, Line 11
There are no primary or candidate keys in the referenced table 'Consumable' that match the referencing column list in the foreign key 'FK_Recipe_Ingredie__59FA5E80'.
Msg 1750, Level 16, State 0, Line 11
Could not create constraint. See previous errors.
What am I doing wrong?
Here's my code;
CREATE TABLE Consumable
(
c_ID int NOT NULL,
Name varchar(32) NOT NULL,
Amount int,
Unit varchar(8) NOT NULL CHECK (unit IN ('ml', 'g', 'pieces', 'unknown')),
CONSTRAINT PK_Consumable PRIMARY KEY (c_ID, Name)
)
CREATE TABLE Recipe
(
Name varchar(64) PRIMARY KEY NOT NULL,
Type varchar(32),
Description varchar(512),
IngredientsID int NOT NULL FOREIGN KEY REFERENCES Consumable(c_ID) ON DELETE CASCADE
)
CREATE TABLE Kitchen
(
K_ID int PRIMARY KEY NOT NULL IDENTITY,
IngredientsID int FOREIGN KEY REFERENCES Consumable(c_ID) ON DELETE CASCADE
)
Read the error message!
It's pretty clear: the foreign key you're trying to set up from Recipe.IngredientsID doesn't reference the primary key of your target table (Consumable - primary key is (c_ID, Name) - not just c_ID ....)
To fix this: you must reference the whole compound PK on your target table (e.g. you must have both columns of PK_Consumable in your child table in order to reference it
CREATE TABLE Recipe
(
Name varchar(64) PRIMARY KEY NOT NULL,
Type varchar(32),
Description varchar(512),
IngredientsID int NOT NULL,
IngredientsName varchar(32) NOT NULL,
CONSTRAINT FK_Recipe_Consumable
FOREIGN KEY (IngredientsID, IngredientsName)
REFERENCES Consumable(c_ID, Name) ON DELETE CASCADE
)
Any foreign key can only ever reference the WHOLE primary key of a parent table - or a unique constraint (again: all columns involved in that unique constraint). You cannot just simply refer to an arbitrary column (or set of columns) in your parent table.
Your Pk is a composite PK and so c_id is not necessarily unique and thus cannot be used in an FK relationship.
You have several choices depending that you had. If you will not have multiple of c_id in the consumables table than you can create a unique index on it and you should be able to create the Fk. BUt in that case really why are you using a compositer OK? The other choice you have in this situation is to make just the c_id the PK and then put a unique index on Name. Never use a composite PK if you don't have to.
If the C_id will into be unique in the Consumable table, then the only choice you have is to add the name column to the Other tables. You would of course have to give it a different name in Recipe since it has a different name.
Ingredients_id doesn't make sense in the recipe table as you are going to have more than one ingredient in a recipe. You should have a child table that contains recipe ingredients.
And On Delete Cascade is a poor choice as well. Very bad thing to do to a nice innocent database. Do you really want to delete the recipes you are out of an ingredient? I don't think so.

creating table having foreign key that reference another table

I am using PGAdminIII database.
I have one table named STOCKREGISTER which contains composite primary key consisting of three fields ie stockregisterId,applicationId and date.
I have to create another table STOCK which has a foreignkey field that reference the field stockregisterId of STOCKREGISTER.If I am trying to create STOCK table,an error message is shown.The error message is "there is no unique contraint matching keys for referenced table STOCKREGISTER".What another step I have to take next
this first table
CREATE TABLE stock_register
(
stock_register_id bigint NOT NULL,
application_id bigserial NOT NULL,
production_date date NOT NULL,
opening_bal bigint DEFAULT 0,
quantity_produced bigint,
total_quantity bigint
CONSTRAINT primarykey PRIMARY KEY (stock_register_id, application_id, production_date),
CONSTRAINT "foreignKey" FOREIGN KEY (application_id)
REFERENCES application (application_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
below is second table.Here I cannot make stock_register_id as a foreign key
CREATE TABLE Stock
(
stock_id bigint NOT NULL,
stock_register_id bigint,
dimension bigserial NOT NULL,
CONSTRAINT "stockid" PRIMARY KEY (stock_id)
)
I guess that syntax should be:
CREATE TABLE Stock
(
stock_id bigint NOT NULL,
stock_register_id bigint,
dimension bigserial NOT NULL,
CONSTRAINT "stockid"
FOREIGN KEY (stock_id)
REFERENCES stock_register (stock_register_id)
)
CREATE TABLE Stock
(
stock_id bigint NOT NULL,
stock_register_id bigint,
dimension bigserial NOT NULL,
CONSTRAINT primaryKey PRIMARY KEY (stock_id),
CONSTRAINT foreignKey FOREIGN KEY(stock_register_id)
REFERENCES stock_register (stock_register_id)
)
That should be everything you need. You'll also have to make sure the DB table engines, collations and charsets match up when using Foreign Keys.
For the unique constraint issue, there doesn't seem to be a problem with your stock_register_id PK in the stock_register table. Based on the name STOCKREGISTER in the error message I suspect it wasn't finding the table stock_register in your second Create statement.
What is a foreign key? A pointer to a specific record in another table.
How is a specific record in stock_register identified according to your DDL? By the unique combination of (stock_register_id, application_id, production_date).
Therefore stock_register_id = 1 could appear on a thousand different records so long as application_id and production_date are different.
Therefore, if all you have is a stock_register_id, there is no way to know which stock_register record it is pointing to and therefore no way for the DBMS to enforce the foreign key.
You must either add application_id and production_date to the stock table and make all three columns together the FK to the composite key on stock_register, or you must remove application_id and production_date from the PK on stock_register so the FK and PK columns match.