Modeling a many-to-many relationship - database

I have two tables, table Project and User. Below is the relationship between these two tables
A Project can be associated with multiple users
A User can operate on multiple projects
I have created below entity relationship. Is this the correct way to represent a many to many relationship?
User:
id
name
email
Project:
id
name
User_Project:
user_id
project_id

Yes, provided you have foreign key relationships (user_id) REFERENCES "user"(id) and (project_id) REFERENCES project(id) defined and a PRIMARY KEY (user_id, project_id).
BTW, try to avoid mixed case names and reserved keywords in table and column names.

Your approach is correct.
Because users can join multiple projects it is necessary to add a junction table.
Junction tables can also contain additional columns.
In your case it might be useful to know when a user joined a project.
So you could add a column join_date where you store that information.
create table users
(
id serial,
name text,
email text,
primary key (id)
);
create table projects
(
id serial,
name text,
primary key (id)
);
create table users_projects
(
user_id int,
project_id int,
join_date date,
primary key (user_id, project_id),
foreign key (user_id) references users (id),
foreign key (project_id) references projects (id)
);

Related

Creating a foreign key against a composite key in MS SQL Server

I'm trying to create a foreign key between two tables. Problem is one of those tables has a composite primary key..
My tables are products (one row per product) and product_price_history (many rows per product).
I have a composite key in product_price_history, which is product id and start date of a specific price for that product.
Here's my code :
CREATE TABLE products (
product_id INT IDENTITY(1,1) PRIMARY KEY,
product_name VARCHAR(50) NOT NULL,
product_desc VARCHAR(255) NULL,
product_group_id INT
)
CREATE TABLE product_price_history (
product_id INT NOT NULL,
start_date DATE NOT NULL,
end_date DATE NULL,
price NUMERIC (6,2) NOT NULL
)
ALTER TABLE product_price_history
ADD CONSTRAINT pk_product_id_start_dt
PRIMARY KEY (product_id,start_date)
Now I'm trying to create a foreign key between the products table and the product_price_history table but I can't because its a composite key.
Also it doesn't make sense to add the start date (the other part of the foreign key) to the products table.
What's the best way to deal with this? Can I create a foreign key between these tables? Do I even NEED a foreign key?
My intentions here are
to enforce uniqueness of the product price information. A product can only have one price at any time.
to link these two tables so there's a logical join between them, and I can show this in a database diagram
The foreign key on the product_price_history table should only include product_id. Your target is to ensure that any entry product_price_history already has "parent" entry in products. That has nothing to do with start_date.
The way I see this situation, in theory, fully normalized version of the tables would have to have current_price as unique value in products table. And the product_price_history is simply a log table.
It's not necessary to do it this way, with a physical field, but thinking from this perspective helps to see where your tables model is slightly de-normalized.
Also, if you make product_price_history table anything but simple log table, how do you ensure that new start_date is newer than previous end_date? You can't even express that as a primary key. What if you edit start_date later? I would even think to create different compaund key for product_price_history table. Perhaps product_id+insert_date or only auto-increment id, while still keeping foreign key relationship to the products.product_id.

Deal with many to many relationships in the same table

I have a table of business names and info about them, including an address column. A business name can have duplicate names and an address can have duplicates, but both the Business name and address cannot be duplicates. So there's a many to many relationship of sorts, but that is not between two tables, it's between two columns on the same table.
One or both of these fields also need to be a foreign key of another table.
Do I create a bridge table? Composite keys? If composite keys, how would I make them foreign keys in another table?
You might want to create 3 tables. One that stores the business names, another for the adresses, and then a junction table called, for example, business_adresses.
create table businesses (
id int primary key,
name varchar(50)
);
create table adresses (
id int primary key,
street varchar(200),
city varchar(200),
country varchar(200)
);
create table business_adresses(
business_id int,
adress_id int,
primary key (business_id, adress_id),
foreign key (business_id) references businesses(id),
foreign key (adress_id) references adresses(id)
);
With this set up, each entity has its own table, and information is not duplicated, unlike when using a single table. Meanwhile, in the junction table, you can efficiently enfore the unicity of business/entity tuples through the primary key (could also be a unique key), and maintain data integrity with foreign keys.

Extending SQL Table

I have 4 SQL tables: User, Student, Professor and Publication.
User has the common columns for any kind of user;
Student has columns specific for a student;
Professor has columns specific for a professor;
Publication is only for professors.
So I have:
create table dbo.[User] (
Id int identity not null
constraint PK_User_Id primary key clustered (Id),
-- Other user columns
)
create table dbo.Student (
UserId int not null
constraint PK_Student_UserId primary key clustered (Id),
-- Other student columns
)
create table dbo.Professor (
UserId int not null
constraint PK_Professor_Id primary key clustered (Id),
-- Other student columns
)
create table dbo.Publication (
Id int identity not null
constraint PK_Publication_Id primary key clustered (Id),
UserId int not null
-- Other student columns
)
alter table dbo.Student
add constraint FK_Student_UserId foreign key (UserId) references dbo.[User](Id);
alter table dbo.Professor
add constraint FK_Professor_UserId foreign key (UserId) references dbo.[User](Id);
alter table dbo.Publication
add constraint FK_Publication_UserId foreign key (UserId) references dbo.Professor(Id);
QUESTION
Should I have a column Id as PK in Professor and Student tables?
And make, for example, (Id, UserId) as the PK of Professor (Same for student)
Then Publication would reference Professor.Id and not Professor.UserId.
I am asking this because it sounds strange to have Publication to reference UserId from Professor table which can be confusing when I will have more tables.
Could someone please advice me on this?
In your current schema arrangement and without knowing your use cases (programmatically), one could make the argument that you don't need the Id identity columns for any of the extension tables. I assume this would be a 1 to 1 relationship to the User table anyway, so you'd at least want a unique constraint on the UserID columns, which you'd get by making it a PK anyway.
Things I like to consider are:
Can a professor ever become a different user ?
Is it possible for a professor to exist without an user ?
Is it possible for a single user to be two professors (multiple disciplines?)
If so, why wouldn't you give every professor an unique Id (ProfessorId), and only create a foreign key to the User table (UserId, you could call this UserFk).
In the publication table you can reference the professor by his/her id and call this one ProfessorFk. This way you create very efficient references between tables. The publication table than also gets a single PublicationId as primary key.
Correct me if i'm wrong, i don't know your use case. But it would seem reasonable that a professor can have multiple publications, but a publication can also be written by multiple professors ? This would mean you need an extra table between publication and professor for the n-n relationship.
About creating a professor key that is a combined key (Id, UserId). I personally dislike combined keys, if you want to reference this professor from your publication table you need two columns.
This would also suggest you can have multiple professors for the same user, if so, go for the single Id option.
This means i would create the following setup:
User Table
UserId
Student Table
StudentId
UserFk
Professor Table
ProfessorId
UserFk
ProfessorPublication Table
ProfessorFk
PublicationFk
Publication Table
PublicationId
So, it partly is based on what you want to be able to do with your data, and partly just your preference.

One to One relationship modeling

I am using access 2010 to do this.
I have created two tables and I would like to get it one to one and i don't seem to get it in to one to one relationship.
CREATE TABLE Person(
ID VARCHAR(1) UNIQUE,
Name VARCHAR(30),
PRIMARY KEY (ID)
);
CREATE TABLE Passport(
ID VARCHAR(1) UNIQUE,
Country VARCHAR(30),
PRIMARY KEY (ID),
FOREIGN KEY (ID) REFERENCES Person(ID)
);
From the little knowledge that I have, This should be a one to one relationship but it is a one to many. How do I get it one to one via ACCESS?
I have tried most things that I can find in books but with no success.
Please help.
You may simply be misled by the way relationships are displayed in the Relationships window. I ran your exact DDL and when I view the relationship in the Relationships window it looks like one-to-many...
...but when I right-click on the line joining the two tables and choose "Edit Relationship..." the dialog shows that it is actually one-to-one:
I beleive that in fact you created a one-to-one relationship as you wish.
the person id is unique
the passport id is unique
the passport id(unique) equals one person id(also unique).
So its one-to-one
However, it should be better design to have different ids for person and passport to have more clear design. Something like this:
CREATE TABLE Person(
PERSONID VARCHAR(1) UNIQUE,
Name VARCHAR(30),
PRIMARY KEY (PERSONID)
);
CREATE TABLE Passport(
PASSPORTID VARCHAR(1) UNIQUE,
Country VARCHAR(30),
PERSONID VARCHAR(1),
PRIMARY KEY (PASSPORTID),
FOREIGN KEY (PERSONID) REFERENCES Person(PERSONID)
);
This will also accomodate cases of persons with multiple passports.

Database Schema Question

If I use the primary key of a table as the primary key of another table is it still a foreign key?
e.g.
Two tables albums and special offers
AlbumId is the primary key in both
How do I represent this relation using primary key foreign key notation?
Yes, it's still a primary key. It's usually called a one-to-one relation.
You can do something like:
create table albums (
album_id integer primary key,
-- other fields...
);
create table special_offers (
album_id integer primary key references albums(album_id),
-- other fields...
);
if e.g you have several special offers for the same album AlbumId is no longer unique in the special offers table. I would think about adding a SpecialOfferId and design a one-to-many relation.
Pablo Santa Cruz is right - yes, you're allowed to do this. However, philosophically, it's only meaningful if there really is a one-to-one relationship - all albums have one and only one special offer, and all special offers have one and only one album.
Guessing from your problem domain, that's not the case - some albums have no special offers, some have 1, some have many.
If that is indeed true, bw_üezi is right - create a one-to-many relationship.
create table albums (
album_id integer primary key,
-- other fields...
);
create table special_offers (
special_offer_id integer primary key,
album_id integer foreign key references albums(album_id),
-- other fields...
);

Resources