Primary Key in three tables - sql

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.

Related

Is it correct to have a table in SQL with just foreign key columns?

Is it correct to have a table in SQL with just foreign key columns? All columns are foreign keys, except the primary key ID.
Here is the scenario in my mind. I wanted to be sure first and then implemented it.
I have three tables => Personnel, Position, Place. Personnel table has general information of employees, Position table has different job positions and tasks in a company, Place table has info about different places in the city. So, an Agent is one of the personnel with one of the job tasks who should go to do the task in one of the places. Agents could change every week, select between personnel and give them almost randomly tasks and places.
I'll give you an example where it is perfectly correct and desired:
when you have many to many relationship, say Table1 and Table2 the best practice states that you should have table, eg. Table1Table2 with just two columns: Table1Id and Table2Id, both foreign keys to respective tables and together they make primary key.
Having said that, it is perfectly correct, as long as it satisfies your design.
To say anything more, you should share your database schema.
you should add a foreign key on the child table referencing the parent table so it is correct that all fields be foreign key but you have to have primary key on that table.

One Primary Key Value in many tables

This may seem like a simple question, but I am stumped:
I have created a database about cars (in Oracle SQL developer). I have amongst other tables a table called: Manufacturer and a table called Parentcompany.
Since some manufacturers are owned by bigger corporations, I will also show them in my database.
The parentcompany table is the "parent table" and the Manufacturer table the "child table".
for both I have created columns, each having their own Primary Key.
For some reason, when I inserted the values for my columns, I was able to use the same value for the primary key of Manufacturer and Parentcompany
The column: ManufacturerID is primary Key of Manufacturer. The value for this is: 'MBE'
The column: ParentcompanyID is primary key of Parentcompany. The value for this is 'MBE'
Both have the same value. Do I have a problem with the thinking logic?
Or do I just not understand how primary keys work?
Does a primary key only need to be unique in a table, and not the database?
I would appreciate it if someone shed light on the situation.
A primary key is unique for each table.
Have a look at this tutorial: SQL - Primary key
A primary key is a field in a table which uniquely identifies each
row/record in a database table. Primary keys must contain unique
values. A primary key column cannot have NULL values.
A table can have only one primary key, which may consist of single or
multiple fields. When multiple fields are used as a primary key, they
are called a composite key.
If a table has a primary key defined on any field(s), then you cannot
have two records having the same value of that field(s).
Primary key is table-unique. You can use same value of PI for every separate table in DB. Actually that often happens as PI often incremental number representing ID of a row: 1,2,3,4...
For your case more common implementation would be to have hierarchical table called Company, which would have fields: company_name and parent_company_name. In case company has a parent, in field parent_company_name it would have some value from field company_name.
There are several reasons why the same value in two different PKs might work out with no problems. In your case, it seems to flow naturally from the semantics of the data.
A row in the Manufacturers table and a row in the ParentCompany table both appear to refer to the same thing, namely a company. In that case, giving a company the same id in both tables is not only possible, but actually useful. It represents a 1 to 1 correspondence between manufacturers and parent companies without adding extra columns to serve as FKs.
Thanks for the quick answers!
I think I know what to do now. I will create a general company table, in which all companies will be stored. Then I will create, as I go along specific company tables like Manufacturer and parent company that reference a certain company in the company table.
To clarify, the only column I would put into the sub-company tables is a column with a foreign key referencing a column of the company table, yes?
For the primary key, I was just confused, because I hear so much about the key needing to be unique, and can't have the same value as another. So then this condition only goes for tables, not the whole database. Thanks for the clarification!

Include a foreign key column in the table?

I have the following situation. My table is:
Table: CompanyEmployees
EmployeeID
Date of Birth
Date Joined
I also want to store the sales information for each employee. I have this:
Table: DealsCompleted
ID
EmployeeID
Deal Name
Deal Amount
My question is this- should there be a column in CompanyEmployees called "DealsCompletedID" which directly refers to the ID column in DealsCompleted, or is it acceptabe to just create a foreign key between the two Employee ID columns? Does this disadvantage the design or potentially distort the normalization?
I am unclear what the rule is as to whether I should include an extra column in CompanyEmployees or not.
EDIT Please assume there will only be one row in the deal table, per employee.
A FOREIGN KEY should point from one table to its referenced row in a parent table, the two tables should generally not reference each other (with foreign keys defined in both).
The FOREIGN KEY is most appropriately defined in the DealsCompleted table, which points back to CompanyEmployees.EmployeeID. Think about it this way - The CompanyEmployees table stores information about employees. Deals they completed do not really count as information about employees. However, the employee who completed a deal is a part of the information about a deal, so the key belongs there.
Having DealsCompleted.EmployeeID will allow for a proper one to many relationship between employees and deals. That is, one employee can have as many related rows in DealsCompleted as needed. Including a DealsCompleted column in the CompanyEmployees table on the other hand, would require you to either duplicate rows about employees, which breaks normalization, or include multiple DealCompletedID values in one column which is also incorrect.
Update after edit above Even if you plan for only a one-to-one relationship (one deal per employee), it is still more appropriate to reference the EmployeeID in DealsCompleted rather than the other way around (or both ways). ...And it allows you to expand to one-to-many, when the need arises.
Assuming that the relationship will always be one-to-one, as you state, then the answer depends on what is the primary entity within the Domain Model. If this database is at its core a database about Deals, and employee data is ancillary, then I would add an EmployeeId FK column in the Deal table. If otoh, this is a database about Employees, and Deals are ancillary, then eliminate the EmployeeId column in the Deal table, and add a DealId FK column to the Employeee table.

Database Modeling - Either/Or in Many-to-Many

I have an either/or type of situation in a many-to-many relationship I'm trying to model.
So I have these tables:
Message
----
*MessageID
MessageText
Employee
----
*EmployeeID
EmployeeName
Team
----
*TeamID
TeamName
MessageTarget
----
MessageID
EmployeeID (nullable)
TeamID (nullable)
So, a Message can have either a list of Employees, or a list of Teams as a MessageTarget. Is the MessageTarget table I have above the best way to implement this relationship? What constraints can I place on the MessageTarget effectively? How should I create a primary key on MessageTarget table?
Database in question is SQL Server 2008
So you want to ensure that MessageTargets for a single message all have the employeeID set or the teamID, but not a mixture of both?
Depending on your RDBMS you might be able to create Materialized view and put a constraint on that. The view would look like
select messageId, count(employeeId), count(teamId) from messageTarget
On that you would place a check constraint ensuring that one of the counts is zero.
Alternatively you could replace the MessageTarget with two tables: EmployeeMessageTarget and TeamMessageTarget, each only containing a TargetId and either an EmployeeId in the first table, and a TeamId in the second table.
Your Message table would get two new fields: an EmployeeMessageTargetId and a TeamMessageTargetId plus a check constraint ensuring at least one of those is null. If you make both fields unique you can have a foreign key from the *MessageTarget tables.
The way you present this, it seems that an Employee is-a MessageTarget and also the Team is-a MessageTarget.
So a Message has a Target which is either an Employee or a Team.
Seems to me this is like inheritence (or composition) problem in SQL.
Check this out "Implementing Table Inheritance in SQL Server" .
An Employee is not a MessageTarget per se but perhaps the readings on this can help you on your modelling
Since employees and teams cannot mix in the same message, you'll need to do something like this:
MessageEmployee.MessageIdForEmployee references Message.MessageIdForEmployee.
MessageTeam.MessageIdForTeam references Message.MessageIdForTeam.
And there is the following constraint on the Message table:
CHECK (
(MessageIdForEmployee = MessageId AND MessageIdForTeam IS NULL)
OR
(MessageIdForEmployee IS NULL AND MessageIdForTeam = MessageId)
)
Note how we have a separate junction table for each kind of child table, and junction tables don't reference parent's PK. Instead each junction table references a separate UNIQUE field. Since only one of these fields can be non-NULL, only one kind of child items can be connected to any given message.
NOTE: It is not strictly necessary to match MessageId with MessageIdForEmployee or MessageIdForTeam, but it may simplify querying somewhat.
you may also consider
MessageTarget
----
MessageID
targetID (not nullable)
targetType
then set the type to whichever it should be...
is-a relationships are often instances of the gen-spec pattern. Class Table Inheritance is one way to design tables for cases of gen-spec.
http://martinfowler.com/eaaCatalog/classTableInheritance.html
Consider removing the the "Team ID" field in the MessageTarget entity so that you only have messageId and employeeId. To cater for the team thing (if it is a requirement that each employee must be a member of a team), you can have another entity "Team Messages" where a database trigger will ensure that on insert into that table, you can insert a row in the message target table for each employee in the team. This way you can conveniently link back from each message to an employee from the MessageTarget table or back to a team from the "Team Messages" table. Also gonna make for convenient access in an ORM framework where the Employee entity simply has a List and the Team also has the same

Constraints instead Triggers (Specific question)

I read here some reasons to use constraints instead of triggers. But I have a doubt. How can be assure (using only constraints), the coherence between SUPERCLASS tables and SUBCLASSES tables?
Whit a trigger is only a matter of check when INS.. UPD...
Is there a way to define that kinda relation by using only constraints (I'm newbie at this), thanks!
You can use constraints to ensure that every ContractEmployees row has a corresponding Employees row, and likewise for SalariedExployees. I don't know of a way to use constraints to enforce the opposite: making sure that for every Employees row, there is a row either in ContractEmployees or SalariedEmployees.
Backing up a bit... there are three main ways to model OO inheritance in a relational DB. The terminology is from Martin Fowler's Patterns of Enterprise Application Architecture:
Single table inheritance: everything is just in one big table, with lots of optional columns that apply only to certain subclasses. Easy to do but not very elegant.
Concrete table inheritance: one table for each concrete type. So if all employees are either salaried or contract, you'd have two tables: SalariedEmployees and ContractEmployees. I don't like this approach either, since it makes it harder to query all employees regardless of type.
Class table inheritance: one table for the base class and one per subclass. So three tables: Employees, SalariedEmployeees, and ContractEmployees.
Here is an example of class table inheritance with constraints (code for MS SQL Server):
CREATE TABLE Employees
(
ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
FirstName VARCHAR(100) NOT NULL DEFAULT '',
LastName VARCHAR(100) NOT NULL DEFAULT ''
);
CREATE TABLE SalariedEmployees
(
ID INT NOT NULL PRIMARY KEY REFERENCES Employees(ID),
Salary DECIMAL(12,2) NOT NULL
);
CREATE TABLE ContractEmployees
(
ID INT NOT NULL PRIMARY KEY REFERENCES Employees(ID),
HourlyRate DECIMAL(12,2) NOT NULL
);
The "REFERENCES Employees(ID)" part on the two subclass tables defines a foreign key constraint. This ensures that there must be a row in Employees for every row in SalariedEmployees or ContractEmployees.
The ID column is what links everything together. In the subclass tables, the ID is both a primary key for that table, and a foreign key pointing at the base class table.
Here's how I'd model a contract vs salary employee setup:
EMPLOYEE_TYPE_CODE table
EMPLOYEE_TYPE_CODE, pk
DESCRIPTION
Examples:
EMPLOYEE_TYPE_CODE DESCRIPTION
-----------------------------------
CONTRACT Contractor
SALARY Salaried
WAGE_SLAVE I can't be fired - slaves are sold
EMPLOYEES table
EMPLOYEE_ID, pk
EMPLOYEE_TYPE_CODE, foreign key to the EMPLOYEE_TYPE_CODE table
firstname, lastname, etc..
If you're wanting to store a hierarchical relationship, say between employee and manager (who by definition is also an employee):
EMPLOYEES table
EMPLOYEE_ID, pk
EMPLOYEE_TYPE_CODE, foreign key to the EMPLOYEE_TYPE_CODE table
MANAGER_ID
The MANAGER_ID would be filled with the employee_id of the employee who is their manager. This setup assumes that an employee could only have one manager. If you worked in a place like what you see in the movie "Office Space", you need a different setup to allow for an employee record to associate with 2+ managers:
MANAGE_EMPLOYEES_XREF table
MANAGER_EMPLOYEE_ID, pk, fk to EMPLOYEES table
EMPLOYEE_ID, pk, fk to EMPLOYEES table
Databases are relational and constraints enforce relational dependencies pretty well, been doing so for some 30 years now. What is this super and sub class you talk about?
Update
Introducing the OO inheritance relationships in databases is actually quite problematic. To take your example, contract-employee and fulltime-employee. You can model this as 1) a single table with a discriminator field, as 2) two unrelated tables, or as 3) three tables (one with the common parts, one with contract specific info, one with fulltime specific info).
However if you approach the very same problem from a traditional normal form point of view, you may end up with a structure similar to 1) or 3), but never as 2). More often than not, you'll end up with something that looks like nothing you'd recommend from your OO design board.
The problem is that when this collision of requirements happens, today almost invariably the OO design will prevail. Often times, the relational model will not even be be on the table. Why I see this as a 'problem' is that most times databases far outlive their original application. All too often I see some design that can be traced back to a OO domain driven design session from an application long forgotten, and one can see in the database schema the places where, over time, the OO design was 'hammered' into place to fit what the relational engine underneath could support, scale and deliver. The tell sign for me is tables organized on a clustered index around a identity ID when no one ever is interrogating those tables for a specific ID.