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.
Related
Can anyone provide some examples of when in a SQL database it's a better choice to keep one-to-one relationships on the same table, and when instead it makes more sense to have them on separate tables?
When you have several entities which all must be able to act as a foreign key to another entity, and the "several entities" have both common properties and unique properties, and you want a NOT NULL constraint on the unique properties (or less important don't want a bunch of NULL values for the unique properties not applicable to the other entity). Even if you didn't have the unique/common properties and didn't care about the NULL values, you might still wish to do so if you wanted individual foreign constraints on each subtpye table as well as the supertype table. This strategy is called supertype/subtype modelling.
Let me give you an example.
peoples
id (PK)
name
age
teachers
id (PK, and FK to people.id)
years_teaching NOT NULL
whatever NOT NULL
students
id (PK, and FK to people.id)
grade NOT NULL
whatever NOT NULL
As you see, teachers and students can have a single common table for some of the properties and can each have their own NOT NULL unique properties. Furthermore, you can JOIN people, teachers, and students to other tables and keep referential integrity.
Another application "might" be if you had separate databases for the each record with some of the properties in one and some in the other, however, I have never done this.
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.
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.
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
I have a table a with primary key id and a table b that represents a specialized version of a (it has all the same characteristics to track as a does, plus some specific to its b-ness--the latter are all that are stored in b). If I decide to represent this by having b's primary key be also a foreign key to a.id, what's the proper terminology for b in relation to a?
A real world example might be a person table with student and teacher add-on tables. A student might also be a teacher (a TA for example) but they're both the same person.
I would call it a 'child table' of a but I already use that as a synonym for 'detail table', like lines on a purchase order, for example.
Your design sounds like Concrete Table Inheritance.
I'd call table B a concrete table that extends table A.
The relationship is one-to-one.
Other answers have suggested storing only the columns specific to the extended table. This design would be called Class Table Inheritance.
Ok this is sort of off topic but first things first, why does B have all of A's columns? It should only have the added columns, ESPECIALLY if you are referencing A with a foriegn key.
"Add on" records are usually called "Detail(s)"
For example, lets say my Table A is "Cars" my Table B would be "CarDetails"
As Neil N said, you shouldn't have the columns in both places if you're referencing table A in table B through a foreign key.
What your describing sounds a bit like a parallel to inheritance in object oriented programming. Personally, I don't use any specific naming convention in this case. I name A what it is and I name B what it is. For example, I might have:
CREATE TABLE People
(
people_id INT NOT NULL,
first_name VARCHAR(40) NOT NULL,
last_name VARCHAR(40) NOT NULL,
...
CONSTRAINT PK_People PRIMARY KEY CLUSTERED (people_id)
)
GO
CREATE TABLE My_Application_Users
(
people_id INT NOT NULL,
user_name VARCHAR(20) NOT NULL,
security_level INT NOT NULL,
CONSTRAINT PK_My_Application_Users PRIMARY KEY CLUSTERED (people_id),
CONSTRAINT UI_My_Application_Users_user_name UNIQUE (user_name)
)
GO
This is just an example, so please don't tell me that my name columns are too long or too short or that they should allow NULLs, etc. ;)
what's the proper terminology for b in relation to a?
Table B is a child of Table A (the parent), because in order for a record to exist in the child, it must first exist in the parent.
Tables should be modeled based on either having one-to-many or many-to-one relationships depending on the context, and of those options they can be either optional or required. Tables that link two sets of lists together will relate to other tables in a many-to-one fashion for every table involved. For example, users, groups, and user_groups_xref - the user_groups_xref can support numerous specific user instances of a user records, and the same relationship to the groups table.
There's no point in one-to-one relationships - these should never be allowed to exist because it should only be one table.