this is probably a simple question but I am quite new to SQL and databases, so I have been following this site: https://www.postgresqltutorial.com/postgresql-foreign-key/ to try and create a table that consist of primary keys from other tables.
Here I have the structure of the database in an excel overview. With colors showing the relations. i am having problems with the One-To-Many tables. As I get the same error every time "ERROR: column "id" referenced in foreign key constraint does not exist
SQL state: 42703".
The SQL query:
DROP TABLE IF EXISTS ingredient_to_unit_relations;
DROP TABLE IF EXISTS ingrediens;
CREATE TABLE ingrediens (
id serial,
name_of_ingredient varchar(255),
price_per_unit int,
PRIMARY KEY (id)
);
CREATE TABLE ingredient_to_unit_relations (
ingredient_relation_id int GENERATED ALWAYS AS IDENTITY,
PRIMARY KEY (ingredient_relation_id),
constraint Fk_ingredient_id
FOREIGN KEY (id)
REFERENCES ingrediens (id)
);
You need to define the column in order to declare it as a foreign key:
CREATE TABLE ingredient_to_unit_relations (
ingredient_relation_id int GENERATED ALWAYS AS IDENTITY,
ingredient_id int,
PRIMARY KEY (ingredient_relation_id),
constraint Fk_ingredient_id FOREIGN KEY (ingredient_id) REFERENCES ingrediens (id)
);
I might recommend some somewhat different naming conventions (I changed the name id in the table above):
CREATE TABLE ingredients (
ingredient_id int GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name varchar(255),
price_per_unit int
);
CREATE TABLE ingredient_to_unit_relations (
ingredient_relation_id int GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
ingredient_id int,
CONSTRAINT Fk_ingredient_id FOREIGN KEY (ingredient_id) REFERENCES ingredients (ingredient_id)
);
Notes:
I am a fan of naming primary keys after the table they are in. That way, foreign keys and primary keys usually have the same name (and you can use using if you choose).
Avoid SERIAL. GENERATED ALWAYS AS IDENTITY is now recommended.
You can inline primary key constraints (as well as other constraints).
There is not generally a need to repeat the table name in a column (other than the primary key). So, name instead of name_of_ingredient.
Using int for a monetary column is suspicious. It doesn't allow smaller units. That might work for some currencies but in general I would expect a numeric/decimal type.
Related
So I went through Odoo database design and I saw that they stored the relationship between 2 tables in a separate table that doesn't have primary key. How are you able to do this? I want to replicate this kind of behavior in SQL Server. Is it auto-inserted?
A table should always have a primary key. Look at the thousands of questions on Stackoverflow that ask how to delete one of two identical rows in a database table.
You typically model m-to-n relationships between tables with a separate table that has foreign keys to both tables:
CREATE TABLE person (
person_id bigint PRIMARY KEY,
name text,
...
);
CREATE TABLE game (
game_id bigint PRIMARY KEY,
name text NOT NULL,
...
);
CREATE TABLE likes_to_play (
person_id bigint REFERENCES person NOT NULL,
game_id bigint REFERENCES game NOT NULL,
PRIMARY KEY (person_id, game_id)
);
CREATE INDEX ON likes_to_play (game_id);
The primary key on the table makes sure there are no superfluous double entries and backs one of the foreign keys. The other index is created for the other foreign key.
For example let's have the following table definition:
CREATE TABLE table1
(
id INT UNIQUE,
name VARCHAR(100) UNIQUE,
description VARCHAR(100),
PRIMARY KEY (id, name)
);
Now I would like to create another table which would have a foreign key to the above composite primary key. Would the following two statements be equivalent?
1)
CREATE TABLE table2
(
id INT PRIMARY KEY,
table1_id INT,
table1_name VARCHAR(100),
FOREIGN KEY (table1_id) REFERENCES table1(id),
FOREIGN KEY (table1_name) REFERENCES table1(name)
);
2)
CREATE TABLE table2
(
id INT PRIMARY KEY,
table1_id INT,
table1_name VARCHAR(100),
FOREIGN KEY (table1_id, table1_name) REFERENCES table1(id, name),
);
I noticed that behind the scenes Postgre SQL creates two FK db objects in the case of 1) and one FK object in the case of 2). Would everything work the same anyway?
Not at all. A foreign key reference should be to the primary key. In this case you have a composite primary key (although that is probably not needed, see below). Although foreign key references to unique keys are allowed (and some databases even allow foreign key references to any indexed columns), that is not a best practice.
When you use a composite primary key (your second example) you are guaranteeing that id/name are aligned in the first table. When you use separate references (your first example), you do not know that they are aligned, so the id could refer to one row in table1 and the name to another row. I doubt that is your intention.
In any case, repeating redundant data among tables is a bad practice. The better data model is:
CREATE TABLE table1 (
id INT PRIMARY KEY,
name VARCHAR(100) UNIQUE,
description VARCHAR(100),
);
CREATE TABLE table2 (
id INT PRIMARY KEY,
table1_id INT,
FOREIGN KEY (table1_id) REFERENCES table1(id)
);
Then, if you want the corresponding name, look up the name in the first table.
As a note, in Postgres, I would expect the INT to really be SERIAL so the database assigns a unique, increasing value when you insert new rows.
If you actually want two references to table1 then use two id references:
CREATE TABLE table2 (
id INT PRIMARY KEY,
table1_id INT,
table1_id_2 INT,
FOREIGN KEY (table1_id) REFERENCES table1(id),
FOREIGN KEY (table1_id_2) REFERENCES table1(id)
);
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)
In my case, I have only 1 candidate may go with 1 job at the time so they are must be 2 primary key.
Then, a column is as JobApplicationId use for the table CandidateDetail as a foreign key.
Is that correct when I decide to set these 3 columns above as primary key or there are other ways to address my problem here?
CREATE TABLE Candidate(
CandidateId int identity primary key,
FullName nvarchar(50)
)
CREATE TABLE Job(
JobId int identity primary key,
JobTitle nvarchar(50)
)
CREATE TABLE JobApplication(
JobApplicationId int identity,
JobId int,
CandidateId int,
CreatedDate datetime,
primary key(JobApplicationId, JobId, CandidateId)
)
CREATE TABLE CandidateDetail(
CandidateDetailId int identity primary key,
JobApplicationId int,
[Description] nvarchar(300)
)
ALTER TABLE JobApplication ADD CONSTRAINT fk_JobApplication_Job FOREIGN KEY (JobId) REFERENCES Job(JobId)
ALTER TABLE JobApplication ADD CONSTRAINT fk_JobApplication_Candidate FOREIGN KEY (CandidateId) REFERENCES Candidate(CandidateId)
ALTER TABLE CandidateDetail ADD CONSTRAINT fk_CandidateDetail_JobApplication FOREIGN KEY (JobApplicationId) REFERENCES JobApplication(JobApplicationId)
Instead of a primary key with three columns you could just have JobApplicationId as the primary key and a unique constraint on JobId, CandidateId.
Otherwise, two rows with JobApplicationId=1, JobId=1, CandidateId=1 and JobApplicationId=2, JobId=1, CandidateId=1 would still be valid in terms of your current primary key approach, but would be invalid in terms of the business case.
From both a performance and usability perspective, a compound primary key can be a hassle and can create performance issues. Personally, I would choose JobApplicationId as the primary key (because this is an identity column and will be unique for each record). Then, if you need to constrain the table so that JobId and CandidateId are always unique (not allowing more than 1 record for any given candidate and the job they've applied for) then I would use a compound Unique Constraint.
However, I would suggest that you evaluate those requirements more closely because what if a candidate applies for the same position in a different time frame? It might stand to reason that having the same candidate applied to the same job more than once in that table might be valid data.
Naive question with the answer "No" , I believe, but still would like to ask.
Table_parent
pk_parent_surrogate
parent_natural_unique_key
Table_child
pk_child_surrogate
child_natural_NOT_unique
Is that true that the only possible declarative relationship among main database vendors is
pk_parent_surrogate ----------< pk_child_surrogate
and we can't have declarative constraint or foreign key in other words for pair
parent_natural_unique_key -------< child_natural_NOT_unique
My answer here is based on my MS SQL knowledge - although I believe the same answer is correct for ANSI standards as well, i'm not 100% sure...
YES - you CAN do this as long as you've got a unique constraint on the column in your parent table that you want to use as the anchor column for the key.
You can create a FOREIGN KEY constraint as part
of the table definition when you create a table.
If a table already exists, you can add a
FOREIGN KEY constraint, provided that the
FOREIGN KEY constraint is linked to an existing
PRIMARY KEY constraints or UNIQUE constraint in
another, or the same, table. A table can contain
multiple FOREIGN KEY constraints.
And as an example of this sort of key...
use tempdb
CREATE TABLE parent(
pk int identity primary key,
candidate_key int unique not null)
CREATE TABLE child(
pk int identity primary key,
join_key int references parent(candidate_key))
See here for more information.
Try code like this:
create table testunique (id int identity(1,1) primary key, otherid int)
go
create unique index ixOther on testunique(otherid)
go
create table testFK (id int identity(1,1) primary key, someid int)
go
alter table testFK add constraint fkTest foreign key (someid) references testunique(otherid)
Rob