How to establish a many to one relationship between 2 tables for a field - sql

I am building an database schema for a project and I am bit stuck on this issue. I have 2 tables:
USER table:
Id Name Contact_ID
1 Arun 2
2 Barath 3
3 Charan 2
4 Dinesh 1
CONTACT table:
ID Name Phone Mail
1 Mahesh 1234 Mahesh#Yahoo.com
2 Suresh 54321 Sureh#Google.com
3 Jayesh 9876 Jayesh#Bing.com
4 Ganesh 98754 Gahesh#Safari.com
Each of the users in USER will have a contact in CONTACT.
If a user has a single contact then I can use a foreign key relationship on Contact_ID in USER and build the relationship between them.
But what if an user in the USER table has multiple contacts in the CONTACT table? I am not sure how to build the relationship between them.
Eg:
In USER for user Charan there is one contact, contact 2, but what if there is one more, contact 4?
In that case how can I build the many to one relationship?

It looks like you've got it backwards. Your CONTACT table should have a foreign key reference to USER table, rather than USER containing a foreign key reference to CONTACT. For example:
USER table
Id Name
1 Arun
2 Barath
3 Charan
4 Dinesh
CONTACT table
ID Name Phone Mail USER_ID
1 Mahesh 1234 Mahesh#Yahoo.com 1
2 Suresh 54321 Sureh#Google.com 2
3 Jayesh 9876 Jayesh#Bing.com 1
4 Ganesh 98754 Gahesh#Safari.com 3
Of course, I just used fake data for the new USER_ID column. As you can see, USER with Id 1 (Arun) has multiple contacts (IDs 1 and 3) in the CONTACT table.

In the relational model (and ER model) tables represent (business/application) relationships/associations. FKs (foreign keys) are called "relationships" by pseudo-relational (& pseudo-ER) methods.
-- user "id" has name "name" and ...
user(id, name, ...)
-- contact "id" has name "name" and ...
contact(id, name, ...)
-- user "uid" has contact "cid"
user_has_contact(uid, cid)
If user_has_contact is N:1 in uid:cid then you can replace user & user_has_contact by:
-- user "id" has ... AND user "id" has contact "cid"
user(id, name, ..., cid)
If user_has_contact is 1:N in uid:cid then you can replace contact & user_has_contact by:
-- contact "id" has ... AND user "uid" has contact "id"
contact(id, name, ..., uid)
You should use the first design for M:M. (You don't actually have to but then the joined tables exhibit problems that normalization would tell you to solve by having the separate tables.) This is called an association/junction/join/many-to-many/bridge table in methods that call FKs "relationships". But like every table it represents a relationship/association on some values. (And hence also any identified entities.) It also handles M:0-or-1 & 0-or-1:M . The other two designs can do that too using NULL.
Regardless of the cardinality of user_has_contact it is probably a good idea to keep the three separate because it is straightforward. (True ER modeling would give the two entity tables & one association table.) But you should realize that there is no need to join them.
A FK tells the DBMS that values for a list of columns in a table must appear as a CK (candidate key) elsewhere. (In SQL, a FK says they appear as a superkey, ie SQL PK (primary key) or UNIQUE NOT NULL, elsewhere.)
(Methods that call FKs "relationships" do so because FKs are associated with relationships like user_has_contact that have be joined into what becomes the referencing table. Also it is those relationships' cardinalities that are called the FKs' cardinalities. But a FK constraint just states a fact; it isn't a relationship/association.)
You need to find & follow references for information modeling & database design.

Related

Confused in how to apply foreign key concept in my scenario

I have a database table called as Receipt, as follows:
The columns
payment
invoice
custom_field
organization
being separate tables
The constraint is that for each receipt there can't be more than one of any from the above. Which means for each receipt there will be one payment entry, one invoice entry, one custom_field and organization entry.
Now I think that I can get rid of all the column names mentioned above and instead associate _id as the primary key for my receipt table and same _id as the foreign key for all other tables.
In the above structure I am also confused as to how should I generate unique values for - payment - invoice - custom_field - organization if I go with the above structure. However if I chose to go with the later the primary and foreign key will be auto generated and unique. I am also concerned about editing. Is there anything helpful you can suggest?
Below is my structure:
Jordi is right, he got the right point. Only I don't think a many-many relationship applies to the original question, as it says "there can't be more than one..."
The constraint is that for each receipt there cant be more than one of
any from the above. Which means for each receipt there will be one
payment entry, one invoice entry, one custom_field and organization
entry.
So, for each Receipt:
One payment.
One Invoice.
One custom field
and so on for as many 'extension' to the receipt table as you need.
If I understand correctly, you could in pure theory put all of those columns into one single "big" table with many columns, which would of course be ugly and bad in practice for other reasons which would be off-topic. But note that if you had one only table, you would also have the same primary key for everything, which is something you seem to have asked, but is also something you probably don't really want.
If you want to denormalize such 'one only big table' into receipt, invoices, customfields and so on... then the receipt table will have a primary key (let say 'ID') as well as any 'extension' and child table will have their primary key (let say 'ID' too).
So we go:
Receipt.ID, Invoice.ID, CustomFields.ID, Payment.ID and so on...
Keep in mind that all of those ids are on their own in relation to Receipt. Invoice.ID and Receipt.ID are not in any way required to be the same.
What you need to 'bind' any one of those children to its parent 'Receipt' is a dedicated column (let say 'ReceiptID') which is foreign-keyed to Receipt.ID.
Now as a last step, if you define an UNIQUE KEY or UNIQUE INDEX on ReceiptID in children tables, it will work to ensure that you will have at most 1 payment, at most 1 invoice etc for any given receipt.
If, for example, in the future you ever need to get more than one custom field for your receipts, or more than one payment information, you simply alter that UNIQUE constraint in customfield table into a simple non-unique INDEX and you are done.
I can't post images because of low reputation.
I hope I was able to make my point clear.
The constraint is that for each receipt there can't be more than one of any from the above.
My fault because fast reading.
UPDATE: ONE-TO-MANY
What you have here is a ONE-TO-MANY relationship, so a simple receipt can have from 0 (or 1?? is mandatory each other table is related with receipt??) to N related users, payment, organization etc...
NOTE: if you can only have a single receipt for each user: 1 to 1 you will need a ONE-TO-ONE relationship.
How to solve it?
You ave to change your vision, you have the foreign keys in the receipt table, and you must have foreign keys in the other tables:
user
|-- id
|-- email
|-- other attributes
|-- receipt_id // foreign key refering to a single receipt.
then your user table will have extra field,
user_id email ..... receipt_id
1 a#a.com others 1
2 b#b.com others 1
3 c#c.com others 2
and you can perform your selects like:
SELECT * FROM USERS WHERE receipt_id = 1
output:
1 a#a.com others 1
2 b#b.com others 1
JOIN QUERY (select receipt and get all users relateds):
SELECT * from receipt r JOIN user u where r.id = u.receipt_id;
MANY-TO-MANY
That means you need a join table to map the many-to-many relationship
Let's explain with user:
One recipe can be refering several users (in real words, various users can access to this recipe, or various users made this recipe).
You will need a table recipe_users with just 2 fields both FOREIGN KEYS:
recipe_users
|---- recipe_id // FK of recipe table
|---- user_id // FK of user table
Then you can refer one recipe with various users
recipe_id user_id
1 1
1 2
1 3
Or have as many recipes as you want for each user,
recipe_id user_id
1 1
2 1
3 1

SQL Table Design: Multiple foreign key columns or general "fkName" and "fkValue" columns

Given a table (Contacts) which could apply to distinct items in a database (Employers, Churches, Hospitals, Government Groups, etc.) which are stored in different tables, when leveraging this single contacts table in the end I've found there exist two choices for relating a contact back to one particular "item"
One column for each "item" type with a Foreign Key association, this results in a table looking like:
contactID empID churchID hospID govID conFN conLN ...
One column indicating the type of "item" (fkName) and one column for the value corresponding to the item of that type (fkValue). This results in a table looking like:
contactID fkName fkValue conFN conLN ...
The first means that out of the X possible foreign keys, X-1 will be NULL, but I get the advantages of hard-associated foreign keys.
The second means that I can set fkName and fkValue as NOT NULL but I don't get the advantages of DB-supported foreign keys.
Ultimately, is there a "right" answer? Are there other advantages / disadvantages that I haven't thought about (performance, security, growth/expansion)?
The second approach is an anti-pattern.
You need to set up many-to-many relationship tables between each entity (Hospitals, Churches, Employers, Government Groups, etc.) and Contacts.
If you want to make it easier to query for all of the entities a contact is related to, consider creating a view on top of the many-to-many relationship tables.
I think the second option is better as it will allow you to maintain referential integrity of your database using the in-built SQL features (foreign keys), rather than relying on your code to maintain it.
This is the solution that you should be going towards:
type
----------------
typeId name
1 hospital
2 church
contact
-----------------------------------------
contactId firstName LastName typeId (fk)
1 bob is 1
2 your uncle 2
If Bob can be a contact for more than one type, than you will need a junction table.

Tables' relationships

I develop simple DB and I have confused with next issue: I have separated entities(tables) for 'Employe', 'Author' and 'Manager'. In table 'Employe' I have column 'Appointment' that can containe some vocation in particular 'Author' and 'Manager' (but it also can containe another vocation for example 'Seller', 'CopyRighter' etc). How can I implement it in my DB? What relationships have I use?
I think you should consider abstracting your vocations into a Role table. Cosider the following structure:
RoleID | RoleName
1 | Author
2 | Manager
3 | Copyrighter
etc...
Then your Appointment column of the Employee table will contain a foreign key (RoleID) to this Role table:

Relationships between two entities

I have a situation:
I have a user (creator) who creates events (Each event belongs to one user)
Each event can invite other users (participants) (Each user belongs to one event)
So basically, there are two entities (Users and Events), but relationships are not simple.
I mean, user who creates event may be not the same who attends it. A user may be just a participant, but not a creator.
The situation is similar to this.
I realised that those relationships are not just many-to-many.
For instance, I may create two tables with two relationships (circular relationship).
To break this circle I need to allow to create a user (participant) without an event by temporarily assigning NULL to it or by creating one more column (Boolean) that indicates whether this user also a creator or not.
But I solved it by creating the third table:
Diagram 1
The third table stores events and their participants.
I also found another way to solve this problem. It involves 4 tables:
User (User can be either a creator or a participant)
Creator (Creator is user who creates event)
Event (Each event belongs to one creator)
Participant (Participant is user who takes part in an event, one event has many participants)
These relationships would look like this:
Diagram 2
Which solution is better?
I liked the one with two tables, but I just needed to dig deeper and find the proper.
I'd stick to the solution with three tables, as an event is always created by one user. The EventMember table solves the n:m relation between User and Event and is necessary.
Introducing a fourth table Creator makes really no sense as it only adds one more JOIN to get the creator of an event.
Rule as originally stated
user who creates event may be not the same who attends it. A user may
be just a participant, but not a creator.
This seems to indicate that, for each event, a given user may be an attendee or a creator but not both.
However, in comments, the OP later stated:
user can be a participant, a creator or both.
The following code is based on the earlier assumption (as I made clear in comments); the only adjustment to accommodate the later clarification is to drop the CHECK constraint:
-- Rule: for each event, a given user may be an attendee or a creator but not both.
-- Rule: each event has zero or one creator.
-- Rule: each event has zero, one or many attendees.
-- General Rule: a table models an entity or a relationship but never both.
CREATE TABLE Users
(
user_name VARCHAR(20) NOT NULL,
UNIQUE (user_name)
);
CREATE TABLE Events
(
event_name VARCHAR(30) NOT NULL,
UNIQUE (event_name)
);
CREATE TABLE EventCreators
(
event_name VARCHAR(30) NOT NULL,
creator_user_name VARCHAR(20) NOT NULL,
UNIQUE (event_name),
UNIQUE (event_name, creator_user_name),
FOREIGN KEY (event_name)
REFERENCES Events (event_name),
FOREIGN KEY (creator_user_name)
REFERENCES Users (user_name)
);
CREATE TABLE EventAttendees
(
event_name VARCHAR(30) NOT NULL,
creator_user_name VARCHAR(20) NOT NULL,
attendee_user_name VARCHAR(20) NOT NULL,
UNIQUE (event_name, attendee_user_name),
FOREIGN KEY (event_name, creator_user_name)
REFERENCES EventCreators (event_name, creator_user_name),
FOREIGN KEY (attendee_user_name)
REFERENCES Users (user_name),
CHECK (creator_user_name <> attendee_user_name)
);
I'd do it this way :
3 tables (like a many to many)
Table 1 : Users
Table 2 : Users_Events
Table 3 : Events
Table 2 would contain :
- FK from Table 1
FK from Table 3
Attribute that is the nature of the relation (organizer or attendee)...this could be turned into a Relation table and then Table 2 would contain a FK to that table instead
the date where the relation was initiated (you're bound to need that at some point :) )
So if we say Bob create an event today, and that Sarah and John are added tomorrow as attendees, you would have ( first column is PK for Table 1 and 2) :
Table 1 1 - Bob 2 - Sarah 3 - John
Table 2 1 - A - Organizer - 05.01.2012 2 - A - Attendee - 06.01.2012 3
- A - Attendee - 06.01.2012
Table 3 A - Super new event
if you want Bob to attend the meeting, then a new record must be created in table 2
1 - A - Attendee - 06.01.2012
Then if you need attendees to the event A, you need to join Table 1 2 and 3 and filter on table_2 for "Attendee"
To avoid double entry in case the organizer attends, you may simply have table 2 this way :
Table 2 would contain :
- FK from Table 1
- FK from Table 3
- Attendee (boolean)
- Organizer (boolean)
This is even more flexible, and for instance if you later need to track who will give a speech in the meeting, you can introduce a new column Speaker without breaking your table. If you foresee many roles, this will not be scalable however

Weak Entity containing a foreign key as a primary key

I have created a table called STUDENT which consists of Unique ID as the PRIMARY KEY along with other related attributes like Name, Addr, Gender etc....
Since I don't want to increase the table size of the STUDENT, I created a weak entity called ACADEMIC RECORDS which stores the previous Academic Records of the student.But in this table i have only created a PRIMARY KEY Unique ID which references the Unique ID of the student. and there is no other attribute in conjunction with Unique ID in the weak entity ACADEMIC RECORD Table.
As I came across the definition OF A WEAK ENTITY which define its primary key as a combination of weak entity's attribute and the owner's table's primary key(in this case STUDENT)
Is my method of creating a foreign key as the only primary key in the table ACADEMIC RECORD correct??
STUDENT Table
**UID** NAME GENDER ADDRESS PHNO.
ACADEMIC RECORD Table
**UID** HighschoolMarks GradSchoolMarks
There's nothing necessarily wrong with having a primary key that's also entirely a foreign key. It's a common way of implementing something like ‘base classes’, where an entity has a row in a base table, and may have a row in one or more extension tables (one to one-or-zero relationship).
I'm not sure it's the most appropriate schema for what you're doing though. If there really is an exactly one-to-one relationship between academic_records and students, it looks like they are part of the same entity to me.
In which case from a normalisation point of view the record columns should be part of the main students table. Maybe there's an efficiency reason to denormalise, but “I don't want to increase the table size” is not normally an adequate reason. Databases can cope with big tables.
I'm not completely clear on what you are asking, but it sounds like you are using the correct method.
Your STUDENT table requires a primary key to provide a unique reference for each row.
Your ACADEMIC_RECORD table also requires a primary key to provide a unique reference for each row.
Each student may have zero or more academic records, and you want to identify the student to which each academic record belongs. You do this by adding a column in the ACADEMIC_RECORD table which contains the id (the primary key) of the student:
STUDENT ACADEMIC_RECORD
id
id <-------> student_id
name high_school_marks
gender grade_school_marks
address
phone_no
Assume you have three students: Alice, Bob and Dave. Alice and Dave have three academic records, and Bob has two. Your tables would look something like this (I've omitted some columns to make things clearer):
STUDENT
id name
1 Alice
2 Bob
3 Dave
ACADEMIC_RECORD
id student_id
1 1
2 1
3 1
4 2
5 2
6 3
7 3
8 3