I am going through a pluralsight course that is currently going through building an MVC application using an entity framework code-first approach. I was confused about the Database schema used for the project.
As you can see, the relationship between Securities and it's relating tables seems to be one-to-one, but the confusion comes when I realize there is no foreign key to relate the two sub-tables and they they appear to share the same primary key column.
The video before made the Securities model class abstract in order for the "Stock" and "MutualFund" model classes to inherit from it and contain all relating data. To me however, it seems that same thing could be done using a couple of foreign keys.
I guess my question is does this method of linking tables serve any useful purpose in SQL or EF? It seems to me in order to create a new record for one table, all tables would need a new record which is where I really get confused.
In ORM and EF terminology, this setup is referred to as the "Table per Type" inheritance paradigm, where there is a table per subclass, a base class table, and the primary key is shared between the subclasses and the base class.
e.g. In this case, Securities_Stock and Securities_MutualFund are two subclasses of the Securities base class / table (possibly abstract).
The relationship will be 0..1 (subclass) to 1 (base class) - i.e. only one of the records in Securities_MutualFund or Securities_Stock will exist for each base table Securities row.
There's also often a discriminator column on the base table to indicate which subclass table to join to, but that doesn't seem to be the case here.
It is also common to enforce referential integrity between the subclasses to the base table with a foreign key.
To answer your question, the reason why there's no FK between the two subclass instance tables is because each instance (with a unique Id) will only ever be in ONE of the sub class tables - it is NOT possible for the same Security to be both a mutual fund and a share.
You are right, in order for a new concrete Security record to be added, a row is needed in both the base Securities Table (must be inserted first, as their are FK's from the subclass tables to the base table), and then a row is inserted into one of the subclass tables, with the rest of the 'specific' data.
If a Foreign Key was added between Stock and Mutual Fund, it would be impossible to insert new rows into the tables.
The full pattern often looks like this:
CREATE TABLE BaseTable
(
Id INT PRIMARY KEY, -- Can also be Identity
... Common columns here
Discriminator, -- Type usually has a small range, so `INT` or `CHAR` are common
);
CREATE TABLE SubClassTable
(
Id INT PRIMARY KEY, -- Not identity, must be manually inserted
-- Specialized SubClass columns here
FOREIGN KEY (Id) REFERENCES BaseTable(Id)
);
Related
I have the following problem that I have multiple scenarios that might be right or wrong, I've been searching on this for a while and I didn't find a specific answer for my problem:
Doctor Clinic Example:
We have doctor, patient, treatment, treatment-type
Doctor: id, name....
Patient: id, name...
Treatment: date, cost
Treatment-Type: id, name
Doctor can do multiple treatments, and Patient can also do multiple treatments, so they are connected with Treatment with(1-N) relationship.
Treatment entity is a weak entity, as it cannot be defined in the absence of Doctor or Patient, so my question is, when we convert this ERD to actual tables, which is the correct (or the best-practice) scenario?
1 - doctor-id, patient-id cannot define the Treatment table uniquely, so we add to Treatment table the treatment-id field, and the PK is (doctor-id, patient-id, treatment-id).
2 - We add treatment-id field, and the PK is(treatment-id).
3 - The PK will be (doctor-id, patient-id, date).
I struggled finding if 'date' can be part of PK or not, and also I struggled if I can create an unique ID for weak entity
Thanks in advance.
Weak entity sets are entity sets that are partially identified by a parent entity set's primary key. A weak entity set necessarily depends on its parent entity set for existence (we say it participates totally in its identifying relationship), but not everything with an existence dependency is a weak entity set. Regular entity sets can also participate totally in one or more relationships. So, it depends on how you identify an entity set. See also my answer to the question "is optionality (mandatory, optional) and participation (total, partial) are same?"
An entity set that is uniquely identified by its own attributes is a regular entity set. An entity set that is partially identified by a parent entity set's primary key is a weak entity set. An entity set that is fully identified by a parent entity set's primary key is a subtype.
You should also note that weak entity sets can only have one parent entity set according to the entity-relationship model as Chen described it. Being identified by multiple parent entity sets would make it a relationship rather than an entity set.
In some schema design tools, a different interpretation is used where tables are equated to entity sets and relationships equated to FK constraints, and an identifying relationship would be an FK that is part of the PK of a table. This approach is closer to the network data model than the entity-relationship model, despite having adopted much of ER's terminology.
Let's take a look at your examples:
In example 1, we should consider whether treatment-id is identifying on its own (i.e. a surrogate key) or only in combination with doctor-id and patient-id (i.e. an ordinal number). If it's a surrogate key, it would be a mistake to include doctor-id and patient-id in the PK, example 2 would be the right way of handling it. If it's an ordinal number, then it's basically the same as example 3 - two foreign entity keys and a value set in a primary key. I'll say more about that in my comments on example 3.
In example 2, treatment-id is a surrogate key which means Treatment is a regular entity set which participates totally in its relationships with Patient and Doctor. This would be my recommended solution, since it's the simplest.
In example 3, you have a primary key consisting of two foreign entity keys and a value set.
The entity-relationship model doesn't cover such relations - relations with a single entity key are called entity relations, and relations with multiple entity keys are called relationships relations. Value sets are only described as the codomains of attributes, not the domains. The ER model's inability to handle arbitrary relations are a consequence of artificial distinctions between entity sets vs value sets, and between attributes vs relationships. Other data modeling disciplines like the relational model and object-role modeling are complete and can handle any kinds of relations.
Back to example 3, despite the ER model's shortcomings, it's not invalid to create such a table/relation in an actual database. However, think about what the primary key means - can a patient receive only one treatment per day from the same doctor? I would think multiple treatments should be possible, in which case you might need to add another ordinal number, e.g. (doctor-id, patient-id, date, treatment-id). In that case, it might be simpler just to do (doctor-id, patient-id, treatment-id).
One argument against such composite/natural keys is that they add up - a many-to-many association between two relations, each with 3 columns in their primary keys, could have up to 6 columns in its primary key! That gets inconvenient quickly, but on the other hand, those columns are relevant related info that would otherwise need to be retrieved from joined tables if the association was identified by a surrogate key.
Sorry about the long answer, but I hope this covers all the fine points. Let me know if you have any questions.
Setup
So here's a scenario which I'm finding is rather common once you decide to play with STI (Single Table Inheritance).
You have some base type with various subtypes.
Person < (Teacher,Student,Staff,etc)
User < (Member,Admin)
Member < (Buyer,Seller)
Vehicle < (Car,Boat,Plane)
etc.
There are two major approaches to modelling that in the database:
Single Table Inheritance
One big table with a type field and a bunch of nullable fields
Class Table Inheritance
One table per type with shared PK (FK'd from the children to the parent)
While there are several issues with STI, I do like how it manages to cut down on the number of joins you have to make, as well as some of the support in frameworks like Rails, but I am running into an issue on how to relate subclass-specific tables.
For example:
Certifications should only reference Teacher-Persons
Profiles should only reference Member-Users
WingInformation should be not be related to a car or boat (unless you are Batman maybe)
Advertisements are owned by Seller-Members not Buyer-Members
With CTI, these relationships are trivial - just slap a Foreign Key on the related table and you're done:
ALTER TABLE advertisements
ADD FOREIGN KEY (seller_id) REFERENCES sellers (id)
But with STI, the similar thing wouldn't capture the subtype restriction.
ALTER TABLE advertisements
ADD FOREIGN KEY (seller_id) REFERENCES members (id)
What I would like to see is something like:
* Does not work in most (all?) databases *
ALTER TABLE advertisements
ADD FOREIGN KEY (seller_id, 'seller') REFERENCES members (id, type)
All I have been able to find is a dirty hack requiring adding a computed column to the related table:
ALTER TABLE advertisements
ADD seller_type VARCHAR(20) NOT NULL DEFAULT 'seller'
ALTER TABLE advertisements
FOREIGN KEY (seller_id, seller-type) REFERENCES members (id, type)
This strikes me as odd (not to mention inelegant).
The real questions
Is there a RDBMS out there which will allow me to do this?
Is there a reason why this isn't even possible?
Is this just one more reason why NOT to use STI except in the most trivial of cases?
There's no standard way to declare a constant in the foreign key declaration. You have to name columns.
But you could force the column to have a fixed value, using one of the following methods:
Computed column
CHECK constraint
Trigger before INSERT/UPDATE to overwrite any user-supplied value with the default value.
I have a class A and a class B that inherits from A. Class A has a certain attribute X. Class B adds another attribute Y. An instance of B is uniquely identified by its pair of attributes {X,Y}. So, {X,Y} is a candidate key for class B. Obviously this key doesn't exist at the class A level since attribute Y isn't there. I use a surrogate key for class A.
Now, I use Hibernate for the object-relational mapping. If I use the TABLE PER SUBCLASS inheritance strategy, I don't see a possibility for defining a UNIQUE constraint on multiple attributes that belong to different classes (and then in the DB, to different tables).
My question is how can I define a unique constraint for this candidate key using Hibernate and more generally in SQL? If it's not possible, what do you recommend?
Thanks
Here are two solutions:
Create a new table with one column which is its PK. This table should hold all the values which you want to make unique. Create foreign keys to this table which will ensure that the domain on the columns comes from the unique table.
Create triggers which raise an error if the condition is violated.
Let's say I have a table that represents a super class, students. And then I have N tables that represent subclasses of that object (athletes, musicians, etc). How can I express a constraint such that a student must be modeled in one (not more, not less) subclass?
Clarifications regarding comments:
This is being maintained manually, not through an ORM package.
The project this relates to sits atop SQL Server (but it would be nice to see a generic solution)
This may not have been the best example. There are a couple scenarios we can consider regarding subclassing, and I just happened to invent this student/athlete example.
A) In true object-oriented fashion, it's possible that the superclass can exist by itself and need not be modeled in any subclasses.
B) In real life, any object or student can have multiple roles.
C) The particular scenario I was trying to illustrate was requiring that every object be implemented in exactly one subclass. Think of the superclass as an abstract implementation, or just commonalities factored out of otherwise disparate object classes/instances.
Thanks to all for your input, especially Bill.
Each Student record will have a SubClass column (assume for the sake of argument it's a CHAR(1)). {A = Athlete, M=musician...}
Now create your Athlete and Musician tables. They should also have a SubClass column, but there should be a check constraint hard-coding the value for the type of table they represent. For example, you should put a default of 'A' and a CHECK constraint of 'A' for the SubClass column on the Athlete table.
Link your Musician and Athlete tables to the Student table using a COMPOSITE foreign key of StudentID AND Subclass. And you're done! Go enjoy a nice cup of coffee.
CREATE TABLE Student (
StudentID INT NOT NULL IDENTITY PRIMARY KEY,
SubClass CHAR(1) NOT NULL,
Name VARCHAR(200) NOT NULL,
CONSTRAINT UQ_Student UNIQUE (StudentID, SubClass)
);
CREATE TABLE Athlete (
StudentID INT NOT NULL PRIMARY KEY,
SubClass CHAR(1) NOT NULL,
Sport VARCHAR(200) NOT NULL,
CONSTRAINT CHK_Jock CHECK (SubClass = 'A'),
CONSTRAINT FK_Student_Athlete FOREIGN KEY (StudentID, Subclass) REFERENCES Student(StudentID, Subclass)
);
CREATE TABLE Musician (
StudentID INT NOT NULL PRIMARY KEY,
SubClass CHAR(1) NOT NULL,
Instrument VARCHAR(200) NOT NULL,
CONSTRAINT CHK_Band_Nerd CHECK (SubClass = 'M'),
CONSTRAINT FK_Student_Musician FOREIGN KEY (StudentID, Subclass) REFERENCES Student(StudentID, Subclass)
);
Here are a couple of possibilities. One is a CHECK in each table that the student_id does not appear in any of the other sister subtype tables. This is probably expensive and every time you need a new subtype, you need to modify the constraint in all the existing tables.
CREATE TABLE athletes (
student_id INT NOT NULL PRIMARY KEY,
FOREIGN KEY (student_id) REFERENCES students(student_id),
CHECK (student_id NOT IN (SELECT student_id FROM musicians
UNION SELECT student_id FROM slackers
UNION ...))
);
edit: #JackPDouglas correctly points out that the above form of CHECK constraint is not supported by Microsoft SQL Server. Nor, in fact, is it valid per the SQL-99 standard to reference another table (see http://kb.askmonty.org/v/constraint_type-check-constraint).
SQL-99 defines a metadata object for multi-table constraints. This is called an ASSERTION, however I don't know any RDBMS that implements assertions.
Probably a better way is to make the primary key in the students table a compound primary key, the second column denotes a subtype. Then restrict that column in each child table to a single value corresponding to the subtype represented by the table. edit: no need to make the PK a compound key in child tables.
CREATE TABLE athletes (
student_id INT NOT NULL PRIMARY KEY,
student_type CHAR(4) NOT NULL CHECK (student_type = 'ATHL'),
FOREIGN KEY (student_id, student_type) REFERENCES students(student_id, student_type)
);
Of course student_type could just as easily be an integer, I'm just showing it as a char for illustration purposes.
If you don't have support for CHECK constraints (e.g. MySQL), then you can do something similar in a trigger.
I read your followup about making sure a row exists in some subclass table for every row in the superclass table. I don't think there's a practical way to do this with SQL metadata and constraints. The only option I can suggest to meet this requirement is to use Single-Table Inheritance. Otherwise you need to rely on application code to enforce it.
edit: JackPDouglas also suggests using a design based on Class Table Inheritance. See his example or my examples of the similar technique here or here or here.
If you are interested in data modeling, in addition to object modeling, I suggest you look up "relational modeling generalization specialization" on the web.
There used to be some good resources out there that explains this kind of pattern quite well.
I hope those resources are still there.
Here's a simplified view of what I hope you'll find.
Before you begin designing a database, it's useful to come up with a conceptual data model that connects the values stored in the database back to the subject matter. Making a conceptual data model is really data analysis, not database design. Sometimes it's difficult to keep analysis and design separate.
One way of modeling data at the conceptual level is the Entity-Relationship (ER) model. There are well known patterns for modeling the specialization-generalization situation. Converting those ER patterns to SQL tables (called logical design) is pretty straightforward, although you do have to make some design choices.
The case you gave of a student having possibly several roles like musician probably doesn't illustrate the case you are interested in, if I read you right. You seem to be interested in the case where the subclasses are mutually exclusive. Perhaps the case where a vehicle might be an auto, a truck, or a motorcycle might be easier to discuss.
One difference you are likely to encounter is that the general table for the superclass doesn't really need the type code column. The type of a single superclass instance can be derived by the presence or absence of foreign keys in the various subclass tables. Whether it's smarter to include or omit the type code depends on how you intend to use the data.
interesting problem. Of course the FK constraints are there for the subtables so there has to be a student for those.
The main problem is trying to check as it is inserted. The student has to be inserted first so that you don't violate a FK constraint in a subtable so a trigger that does a check wouldn't work.
You could write an app that checks now and then if you are really concerned about this. I think the biggest fear though would be deletions. Someone could delete a subtable entry but not the student. You could have triggers to check when items are deleted from the subtables since that is probably the biggest problem.
I have a db with a table per subclass hierarchy like this as well. I use Hibernate and its mapped properly so it deletes everything automatically. If doing this by 'hand' then I would make sure to always delete the parent with proper cascades hehe :)
Thanks, Bill. You got me thinking...
The superclass table has a subclass code column. Each of the subclass tables has a foreign key constraint, as well as one that dictates that the id exist with a subset of the superclass table (where code = athlete).
The only missing part here is that it's possible to model a superclass without a subclass. Even if you make the code column mandatory, it could just be an empty join. That can be fixed by adding a constraint that the superclass's ids exist in a union of the ids in the subclass tables. Insertion gets a little hairy with these two constraints if constraints are enforced in the middle of transactions. That or just don't worry about unsubclassed objects.
Edit: Bleh, such a good sounding idea... But impeded by the fact that subqueries that refer to other tables aren't supported. At least not in SQL Server.
That can be fixed by adding a constraint that the superclass's ids exist in a union of
the ids in the subclass tables.
Depending on how much intelligence you want to put into your schema (and how much MS SQL Server lets you put there), you wouldn't actually need to do a union of the subclass tables, since you know that, if the id exists in any subclass table, it must exist in the same subclass as the one identified by the subclass code column.
I would add a Check Constraint possibly.
Create the ForeignKeys as Nullable.
Add a Check to make sure they aren't both null and to make sure they aren't both set.
CONSTRAINT [CK_HasOneForiegnKey] CHECK ((FK_First!= NULL OR FK_Second != NULL) AND NOT (FK_First != NULL AND FK_Second != NULL)).
I am not sure but I believe this would allow you to set only one key at a time.
I hear a lot about subtyping tables when designing a database, and I'm fully aware of the theory behind them. However, I have never actually seen table subtyping in action. How can you create subtypes of tables? I am using MS Access, and I'm looking for a way of doing it in SQL as well as through the GUI (Access 2003).
Cheers!
An easy example would be to have a Person table with a primary key and some columns in that table. Now you can create another table called Student that has a foreign key to the person table (its supertype). Now the student table has some columns which the supertype doesn't have like GPA, Major, etc. But the name, last name and such would be in the parent table. You can always access the student name back in the Person table through the foreign key in the Student table.
Anyways, just remember the following:
The hierarchy depicts relationship between supertypes and subtypes
Supertypes has common attributes
Subtypes have uniques attributes
Subtypes of tables is a conceptual thing in EER diagrams. I haven't seen an RDBMS (excluding object-relational DBMSs) that supports it directly. They are usually implemented in either
A set of nullable columns for each property of the subtype in a single table
With a table for base type properties and some other tables with at most one row per base table that will contain subtype properties
The notion of table sub-types is useful when using an ORM mapper to produce class sub-type heirarchy that exactly models the domain.
A sub-type table will have both a Foreign Key back to its parent which is also the sub-types table's primary key.
Keep in mind that in designing a bound application, as with an Access application, subtypes impose a heavy cost in terms of joins.
For instance, if you have a supertype table with three subtype tables and you need to display all three in a single form at once (and you need to show not just the supertype date), you end up with a choice of using three outer joins and Nz(), or you need a UNION ALL of three mutually exclusive SELECT statements (one for each subtype). Neither of these will be editable.
I was going to paste some SQL from the first major app where I worked with super/subtype tables, but looking at it, the SQL is so complicated it would just confuse people. That's not so much because my app was complicated, but it's because the nature of the problem is complex -- presenting the full set of data to the user, both super- and subtypes, is by its very nature complex. My conclusion from working with it was that I'd have been better off with only one subtype table.
That's not to say it's not useful in some circumstances, just that Access's bound forms don't necessarily make it easy to present this data to the user.
I have a similar problem I've been working on.
While looking for a repeatable pattern, I wanted to make sure I didn't abandon referential integrity, which meant that I wouldn't use a (TABLE_NAME, PK_ID) solution.
I finally settled on:
Base Type Table: CUSTOMER
Sub Type Tables: PERSON, BUSINESS, GOVT_ENTITY
I put nullable PRERSON_ID, BUSINESS_ID and GOVT_ENTITY_ID fields in CUSTOMER, with foreign keys on each, and a check constraint that only one is not null. It's easy to add new sub types, just need to add the nullable foreign key and modify the check constraint.