How can i fix A column referencing multiple tables? - sql

I have 4 tables:
ConditionalOffer (PK ID, Description,...)
UnconditionalOffer (PK ID, Description,...)
Offer (PK ID,
Offer FOREIGN KEY REFERENCES ConditionalOffer.ID,
Offer FOREIGN KEY REFERENCES UnconditionalOffer.ID)
Applicant (ID, Offer FOREIGN KEY REFERENCES Offer.ID,...)
I know that my codes were wrong at table Offer because of a column be cannot referencing multiple tables. How can I fix this?

A column can be part of more than one foreign key constraint, but your syntax isn't correct as you specify the source column twice.
Instead either use inlined constraints like this:
create table Offer (
ID int primary key,
Offer int
FOREIGN KEY (offer) REFERENCES ConditionalOffer (ID),
FOREIGN KEY (offer) REFERENCES UnconditionalOffer (ID)
);
Or use explicitly named constraints (which might be cleaner):
create table Offer (
ID int primary key,
Offer int,
constraint fk_cond FOREIGN KEY (offer) REFERENCES ConditionalOffer (ID),
constraint fk_uncond FOREIGN KEY (offer) REFERENCES UnconditionalOffer (ID)
);
While this is possible, it does however raise questions about the database design: are the IDs in ConditionalOffer and UnconditionalOffer really the same? How are they kept in sync? Shouldn't those tables be one entity if they share primary key (with the differences refactored to other tables)?

Related

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.

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)

Can a foreign key reference another foreign key

Is it possible to have a foreign key that references another foreign key in a different table, or can it only reference primary and unique keys?
A foreign key can reference any field defined as unique. If that unique field is itself defined as a foreign key, it makes no difference. A foreign key is just to enforce referential integrity. Making a field a foreign key doesn't change the field itself in any way. If it is a unique field, it can also be the target of another FK.
For example:
create table Table1(
PK int identity primary key,
...
);
create table Table2( -- 1-1 relationship with Table1
PKFK int primary key,
...,
constraint FK_Table2_1 foreign key( PKFK ) references Table1( PK )
);
create table Table3( -- relates to Table2
PKFKFK int primary key,
...,
constraint FK_Table3_2 foreign key( PKFKFK ) references Table2( PKFK )
);
I know of no DBMS where this is not the case. And I agree with Horse, there is nothing wrong with the practice.
Is it possible to have a foreign key that references another foreign key in a different table
Yes. In fact contrary to accepted answer, the referenced FK column doesn't even have to be unique! - at least in MySQL. see https://www.db-fiddle.com/f/6RUEP43vYVkyK2sxQQpBfj/0 for a demo of the same.
which brings up the question that if the FK is not unique in the parent table, then who is the parent row? The purpose of FKs is to establish parent-child relationship.

What's the difference between these SQL syntaxes?

I was looking for info on foreign keys.... AGAIN! ... and happened to notice on webschools.com they have different examples of the same thing. for the foreign key example they have
CREATE TABLE Orders
(
O_Id int NOT NULL,
OrderNo int NOT NULL,
P_Id int,
PRIMARY KEY (O_Id),
FOREIGN KEY (P_Id) REFERENCES Persons(P_Id)
)
CREATE TABLE Orders
(
O_Id int NOT NULL PRIMARY KEY,
OrderNo int NOT NULL,
P_Id int FOREIGN KEY REFERENCES Persons(P_Id)
)
CREATE TABLE Orders
(
O_Id int NOT NULL,
OrderNo int NOT NULL,
P_Id int,
PRIMARY KEY (O_Id),
CONSTRAINT fk_PerOrders FOREIGN KEY (P_Id)
REFERENCES Persons(P_Id)
)
now..........
what's the difference?...
How do I know which one I'm suppose to use for my database? I have a feeling this will help resolve a lot of the confusion I'm having with SQL...
No difference in effect: They achieve exactly the same thing.
I prefer the in-line version, because it puts the fk definition as close to the column definition as possible.
There's a 3rd way - a separate alter table statement (which I think is the "official" way):
alter table orders
add contraint fk_PerOrders
foreign key p_id references persons(p_id);
You may find some databases don't support one version or the other.
All of them are doing same thing. Use the one which you feel is easy to understand.
All do same (three ways):
In first, you first defined P_Id as int then defined foreign key constraint.
In second, P_Id int FOREIGN KEY REFERENCES Persons(P_Id). P_Id is defecation and foreign key constraint defecation in same line.
In third, a foreign key constraint name is also give fk_PerOrders. that can be useful later when you wants to drop constraint. e.g.
ALTER TABLE Orders
DROP FOREIGN KEY fk_PerOrders
Its always good practice to give name to a constraint.

Why is this a cyclical foreign key constraint?

I came upon this code, marked "error," in an application I'm to update. Running it on a test database gives a cyclical reference error:
The referential relationship will result in a cyclical reference that is not allowed (Constraint name = descriptions_fk_2)
I named the constraints to see which one caused the problem.
CREATE TABLE items (
id INT NOT NULL UNIQUE IDENTITY,
name NCHAR(100) NOT NULL UNIQUE,
PRIMARY KEY (id)
);
CREATE TABLE sources (
id INT NOT NULL UNIQUE IDENTITY,
item_id INT NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (item_id)
REFERENCES items(id) ON UPDATE NO ACTION ON DELETE CASCADE
);
CREATE TABLE descriptions (
id INT NOT NULL UNIQUE IDENTITY,
item_id INT NOT NULL,
source_id INT NOT NULL,
PRIMARY KEY (id),
CONSTRAINT descriptions_fk_1 FOREIGN KEY (item_id)
REFERENCES items(id) ON UPDATE NO ACTION ON DELETE CASCADE,
CONSTRAINT descriptions_fk_2 FOREIGN KEY (source_id)
REFERENCES sources(id) ON UPDATE NO ACTION ON DELETE CASCADE
);
Why is this a cyclical reference? The descriptions table is linked to two separate tables, but none of them link back to descriptions.
It's not strictly cyclical - but there are multiple cascade paths. So you could cascade delete a row in items two ways:
1) description -> item
2) description -> source -> item
And, for that reason, it's disallowed.
I believe it's a performance concern, as PostGres will allow cycles like that and will just work it out, but deletes under those circumstances can be quite slow.
For some further reading about why it's disallowed, please see this answer.