multi keys and many-to-many relationship - database

Lets say I have two tables teams and players and we assume that many players can be members of many teams(in different sports). Thus I have the first table
teams with PKs both team_name and sport. the second table "players" has PK player_id. Due to the -to- relationship I have also a third table with all the keys (team_name, sport and player_id).
the problem in this case is that the column team name is not unique in the first table. Of course I could give another column as the id and make this one the PK. But I am not sure if this is the best approach and how this is solved in the real world. So the questions are:
1. if I can have a composite key like this which one column doesnt have unique values
2. How do you normalize it appropriately?
3. Could I use just one of the composite key in the third table if this is convenience or I always have to take the whole key?
create table sports(
sport varchar(30),
capt_id int references captain(capt_id),
primary key(sport)
);
Create table teams(
team varchar(30),
sport varchar(30) references sports(sport),
primary key(team,sport)
);
create table teamplayer(
player_id int references player(player_id),
sport varchar(30) references sports(sport),
team varchar(30) references teams(team),
unique (team, sport),
primary key(player_id, team, sport)
);

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.

Pledges table normalize

I have this table and I don't know how to normalize.
1st table name, address, landline no., mobile no., e-mail ad, amount, and registration number https://docs.google.com/file/d/0B99TeByt30n2dDVLVHV4dU1yRFE/edit
and in the second table will be their monthly pledges. https://docs.google.com/file/d/0B99TeByt30n2TVh4c1dmLTFYOWs/edit
PersonTable
PersonId int primary key
Name varchar(50)
Addresss varchar(50)
etc.
PledgeTable
PledgeId int primary key,
PersonId int foreign key references PersonTable(PersonId)
PledgeDate datetime
PledgeAmount decimal(10,2)
Ok.
You have to re engineer the whole idea.
I will give you a few concepts to understand what to do.
Keep in mind that we must NOT to have data duplicates.
So an array can be named Customer.
Customer can have a customer id column, named c_id for instance.
c_id must be defined as integer UNIQUE Auto_Increment NOT NULL
That means that it's an attribute that grants each customer its uniqueness.
A customer might have same name and same surname with another customer, but never same c_id.
Auto increment means that the first entry will be automatically numbered with c_id = 1, the next 2 etc etc.
Keep in mind that if you pass a record in the database using PHP, you enter null as value for c_id. Auto Incremet does the job then.
So you got a customer table and its first attribute that will be defined as the Primary key.
For example here is a small table:
CREATE TABLE customer
(c_id integer UNIQUE Auto_Increment NOT NULL,
c_name varchar(100),
c_surname varchar(100),
c_address varchar(100),
PRIMARY KEY (c_id)
);
You have to add all the attributes the customer has in the table.
That was just an example.
PRIMARY KEY (c_id) line in the end,
sets c_id as the primary key that distinguishes each record as unique.
Then you got another table.
A Pledge table.
CREATE TABLE pledge
(pl_id integer UNIQUE Auto_Increment NOT NULL,
pl_date date,
pl_price double(9,2),
pl_c_id integer,
PRIMARY KEY (pl_id),
FOREIGN KEY (pl_c_id) REFERENCES customer (c_id));
What is new here?
Line:
pl_c_id integer,
and line:
FOREIGN KEY (pl_c_id) REFERENCES customer (c_id)
What happens here, is that you create a column, that will contain an existing c_id!
That way, you make a reference to a customer, by using his/her UNIQUE c_id.
This is defined as integer, so it can fit the key.
pl_c_id MUST be the same type as the primary key of the other table. Ok?
Also SQL will know what key we refer to, by reading the line:
FOREIGN KEY (pl_c_id) REFERENCES customer (c_id)
In plain English that means:
pl_c_id can be filled with values already declared in a Primary Key of another Table, named "customer" that uses as primary key the column named "c_id".
Got it?
Now you got the flexibility to use ANY date.
That is more normalized than what you got.
Usually a 3NF (Third Normal Form) you will be ok.
Oh! Not to mention that you can Google "3NF" or "Third Normal Form" and get nice results for your reference.
;)
Cheers.
Edit: Made this reply more simple to understand.

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.

When should I combine two foreign keys as a single foreign key?

My teach said I should combine two foreign keys into a single primary key. But my thought process is that that would allow for only one combination of each foreign key.
Imagine I have a Product, Purchase, PurchaseDetail.
In PurchaseDetail I have two foreign keys, one for product and one for purchase. My teacher said that I should combine these two foreign keys into a single one. But can't a product be in many different purchases? And many purchases have many products?
I'm confused.
Thanks!
Edit: This is the SQL my teacher saw and then gave feedback upon. Thanks for the guidance guys. (I changed the essential to English)
create table Purchase
(
ID int primary key identity(1,1),
IDCliente int foreign key references Cliente(ID),
IDEmpleado int foreign key references Empleado(ID),
Fecha datetime not null,
Hora datetime not null,
Amount float not null,
)
create table PurchaseDetail
(
ID int primary key identity(1,1),
IDPurchase int foreign key references Purchase(ID),
IDProductOffering int foreign key references ProductOffering(ID),
Quantity int not null
)
create table Product
(
ID int primary key identity(1,1),
IDProveedor int foreign key references Proveedor(ID),
Nombre nvarchar(256) not null,
IDSubcategoria int foreign key references Subcategoria(ID),
IDMarca int foreign key references Marca(ID),
Fotografia nvarchar(1024) not null
)
create table ProductOffering
(
ID int primary key identity(1,1),
IDProduct int foreign key references Product(ID),
Price float not null,
OfferDate datetime not null,
)
Maybe I'm confused about good database schema design. Thanks again!
I imagine he's suggesting:
Product - one primary key (product id), which implies a unique product id
Purchase - one primary key (purchase id), which implies a unique purchase id
PurchaseDetail - two foreign keys (product id),(purchase id), plus one unique constraint on (product id + purchase id)
Plus some people argue that all tables should have their own primary key that doesn't depend on anything else (purchase detail id). Some DBMS make this mandatory.
This means that you can't have two rows in PurchaseDetail that have the same product and purchase. That makes sense, assuming there is also a quantity column on PurchaseDetail, so that one purchase can have more than one of each product.
Note that there is a difference between a unique constraint and a foreign key. A foreign key merely says that there should be an item with that id in the parent table - it will let you create as many references to that item as you want in the child table. You need to specify that the column or combination of columns are unique if you want to avoid duplicates. A primary key on the other hand implies a unique constraint.
Exact syntax for defining all of this varies by language, but those are the principles.
I don't agree with the single key, but they could be a compound key (which I tend to dislike). They can be two different fields each restricted to the ID in the corresponding tables.
Not sure why the same product iD would need to be listed more than once for a single purchase? Isn't that why you indicate quantity? Maybe the need to do a separate line item for a purchase and a discount?
I believe thelem has answered correctly. But there is another option. You could add a new primary key column to the details table, so it looks like this:
detail_id int (PK)
product_id int (FK)
purchsae_id int (FK)
This is not really necessary, but it could be useful if you need to ever need to reference the details table as a foreign key - having a single primary key field makes for smaller indexes and foreign key reference (and they are a little easier to type).
That depends on what data you need to represent.
If you use the two foreign keys as the primary key for the purchase detail, a product may only occur once in each purchase. A purchase may however still contain many products, and a product may still occur in many purchases.
If the purchase detail contains more information, you may need to be able to use a product more than once in a purchase. For example if the purchase detail contains size and color, and you want to by a red T-shirt size XL and a blue T-shirt size S.
Perhaps he is suggesting a many-to-many table where it's Primary Key is comprised of the Foreign Keys to the mapped tables:
PurchaseDetail:
ProductId int (FK)
PurchaseId int (FK)
PK(ProductId, PurchaseId)
This can also be modelled as
PurchaseDetail:
PurchaseDetailId int (PK, Identity)
ProductId int (FK)
PurchaseId int (FK)
The second form is useful if you want to refer to Purchase details elsewhere in your model, and also in some RDBMS's it is beneficial to have a PK on a montonically increasing integer.

Resources