How to design a circular reference to a single database table with an added relationship? - sql

I'm not sure how best to phrase the question, but essentially I have a table of contacts, and instead of doing the typical -- a contact has a reference to a table with spouse information, and a table with children, I want each of those people to be a contact, but then define a relationship between those contacts (brother, sister, child, spouse, etc.). So the contacts would exist in a single table, but I'm having trouble determining how best to define the relationship based upon their contact id and the relationship type. Any advice would be appreciated.

CONTACTS table
contact_id, pk
CONTACT_RELATIONSHIP_TYPE_CODE table
contact_relationship_type_code, pk
description
CONTACTS_RELATIONS table
parent_contact_id, pk, foreign key to CONTACTS table
child_contact_id, pk, foreign key to CONTACTS table
contact_relationship_type_code, foreign key to CONTACT_RELATIONSHIP_TYPE_CODE table
If you see the need to support multiple relationship types to a pair of people, add the CONTACTS_RELATIONS.contact_relationship_type_code column to the composite primary key

This is called a self join, it is pretty common and fairly easy to provide the functionallity you mention above. Take a look at this article.

Just implement an intersect table with four columns - key, contactid #1, contact id#2, and relationship.
Why do it this way? Because a contact can have several relationships.

Related

SQL Server use same Guid as primary key in 2 tables

We have 2 tables with a 1:1 relationship.
1 table should reference the other, typically one would use a FK relationship.
Since there is a 1:1 relationship, we could also directly use the same Guid in both tables as primary key.
Additional info: the data is split into 2 tables since the data is rather separate, think "person" and "address" - but in a world where there is a clear 1:1 relationship between the 2.
As per the tags I was suggested I assume this is called "shared primary key".
Would using the same Guid as PK in 2 tables have any ill effects?
To consolidate info from comments into answer...
No, there are no ill effects of two tables sharing PK.
You will still need to create a FK reference from 2nd table, FK column will be the same as PK column.
Though, your example of "Person" and "Address" in 1:1 situation is not best suited. Common usage of this practice is entities that extend one another. For example: Table "User" can hold common info on all users, but tables "Candidate" and "Recruiter" can each expand on it, and all tables can share same PK. Programming language representation would also be classes that extends one another.
Other (similar) example would be table that store more detailed info than the base table like "User" and "UserDetails". It's 1:1 and no need to introduce additional PK column.
Code sample where PK is also a FK:
CREATE TABLE [User]
(
id INT PRIMARY KEY
, name NVARCHAR(100)
);
CREATE TABLE [Candidate]
(
id INT PRIMARY KEY FOREIGN KEY REFERENCES [User](id)
, actively_looking BIT
);
CREATE TABLE [Recruiter]
(
id INT PRIMARY KEY
, currently_hiring BIT
, FOREIGN KEY (id) REFERENCES [User](id)
);
PS: As mentioned GUID is not best suited column for PK due to performance issues, but that's another topic.

Primary Key in three tables

Just curious if I can have the same primary key in 3 different tables? I am going to create an Employee, FullTime and PartTime tables. I would like to make an EmployeeID the primary key for all 3. Any thoughts?
You can have the primary key EmployeeId in a table called Employees. This would have common information, such as date of hire and so on.
Then, each of your subtables can have an EmployeeId that is both a primary key in the table and a foreign key reference to Employees.EmployeeId. This is one way to implement a one-of relationship using relational tables.
Unfortunately, unless you use triggers, this mechanism doesn't prevent one employee from being in the two other tables, but that is not part of your question.
It sounds like your design is wrong.
The entity is the employee
An attribute of an employee is their [current^] employment status.
Therefore, in its simplest form, you need a single employee table, with a column that indicates their status.
To improve this further, the employee status column should have a foreign key relationship with another table that stores the possible employee statuses.
^ current status is a 1:1 relationship. If you wanted the history of changes, this is a 1:M and needs modelling differently.

How to model many-to-many relationships in SQL?

I have a major problem with my SQL design.
I need to create a database which models the following situation:
I have a list of capitals, it looks like this: Berlin, London, Prague, you get it. The other list is a list of travellers: John, Kyle, Peter etc.
The database needs to be able to answer queries such as: List of cities a given Traveller has visited, what Travellers has visited a given City and so on.
My problem is that when I create the two tables I just freeze and am unable to figure out the connection between them that would allow me to implement the intended behaviour.
I read up on it on the internet and I was told to use intersection entities, which I can, but I just don't see how that would help me. Sorry if this is a FAQ, but I just could not get my head around the proper keywords for a search.
Isn't it easier to create third table like travelers_cities with to foreign keys traveler and city, than you jan join that table with table you need and look for result there?
Solution:
Follow the following schema
First Table: Capital
Let say two columns: cid (Primary Key), Name
Second Table: Travellers
Let say two columns: tid (Primary Key), Traveller_Name
Now there is a many to many relationship that one traveller can travel/visit one or many capitals and one capital can be visited by one or many visitors.
Many to many relationship can be acheived by creating a new table which will act as reference/mapping table. let say "capital_travellers"
So, This third table will have following columns
capital_travellers:
id (Primary key): Its optional
cid (Primary key of Capital Table will work as Foreign key)
tid (Primary key of traveller Table will work as Foreign key)
Now when you want to fetch records, you will look into this table(capital_travellers).
I hope it helps.
In a many to many relationship it is necessary to implement a third junction table between the two entities. We could, say, name it travel. This table uses two foreign keys, one from each entity, to form one compound key.
Now you have 3 tables. One table called 'Traveller', one called called 'City' and a third junction table called 'Travel'. Lets assume the primary key for traveller is travellerId and for city it's cityId. The junction table takes these two keys to form a primary key for the entity 'Travel'. When u query the database for which cities a traveller with travelId '031' has travelled to it would make use of this junction table and return the cityId's to you.
If this doesn't help or if you need more clarification I recommend searching these terms:
Many-to-many
Cardinality

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.

If I have two tables in SQL with a many-many relationship, do I need to create an additional table?

Take these tables for example.
Item
id
description
category
Category
id
description
An item can belong to many categories and a category obviously can be attached to many items.
How would the database be created in this situation? I'm not sure. Someone said create a third table, but do I need to do that? Do I literally do a
create table bla bla
for the third table?
Yes, you need to create a third table with mappings of ids, something with columns like:
item_id (Foreign Key)
category_id (Foreign Key)
edit: you can treat item_id and category_id as a primary key, they uniquely identify the record alone. In some applications I've found it useful to include an additional numeric identifier for the record itself, and you might optionally include one if you're so inclined
Think of this table as a listing of all the mappings between Items and Categories. It's concise, and it's easy to query against.
edit: removed (unnecessary) primary key.
Yes, you cannot form a third-normal-form many-to-many relationship between two tables with just those two tables. You can form a one-to-many (in one of the two directions) but in order to get a true many-to-many, you need something like:
Item
id primary key
description
Category
id primary key
description
ItemCategory
itemid foreign key references Item(id)
categoryid foreign key references Category(id)
You do not need a category in the Item table unless you have some privileged category for an item which doesn't seem to be the case here. I'm also not a big fan of introducing unnecessary primary keys when there is already a "real" unique key on the joining table. The fact that the item and category IDs are already unique means that the entire record for the ItemCategory table will be unique as well.
Simply monitor the performance of the ItemCategory table using your standard tools. You may require an index on one or more of:
itemid
categoryid
(itemid,categoryid)
(categoryid,itemid)
depending on the queries you use to join the data (and one of the composite indexes would be the primary key).
The actual syntax for the entire job would be along the lines of:
create table Item (
id integer not null primary key,
description varchar(50)
);
create table Category (
id integer not null primary key,
description varchar(50)
);
create table ItemCategory (
itemid integer references Item(id),
categoryid integer references Category(id),
primary key (itemid,categoryid)
);
There's other sorts of things you should consider, such as making your ID columns into identity/autoincrement columns, but that's not directly relevant to the question at hand.
Yes, you need a "join table". In a one-to-many relationship, objects on the "many" side can have an FK reference to objects on the "one" side, and this is sufficient to determine the entire relationship, since each of the "many" objects can only have a single "one" object.
In a many-to-many relationship, this is no longer sufficient because you can't stuff multiple FK references in a single field. (Well, you could, but then you would lose atomicity of data and all of the nice things that come with a relational database).
This is where a join table comes in - for every relationship between an Item and a Category, the relation is represented in the join table as a pair: Item.id x Category.id.