Implementing super-type subtype correctly in MySQL
Below is a diagram of a database in which I am trying to determine the appropriate design for. Here are a few notes.
- Employees/managers are associated with customers.
- The partyid is a way to globally represent a person; customer, employee, manager. 开发者_开发百科Does it need to propagate all the way down? Should it be a primary key in all tables or just the tables that represent an individual?
- Do the other tables such as billing, reporting, credential, etc tables need to have their own respective id's that are primary keys, e.g. billingid, reportingid, credentialid, etc?
Some notes about the interaction of the entities.
- employees have a manager(s) associated with them.
- customers have a manager(s) and possibly employees associated with them.
- customers and employees will need to report time billed.
The table "party" doesn't look right. Compare to the source code from this other SO question.
In this kind of structure, the party id number does propagate downward, so to speak. It should usually be either a primary key or a foreign key in tables that store data about a person.
In your table "reporting", it looks like the primary key shouldn't be 'partyid'. That would allow only one row per employee, which I don't think you intended. (I could be wrong.) If I'm right about that, you might consider a NOT NULL UNIQUE
constraint on {partyid, date}, and a PRIMARY KEY
constraint on a new column, 'reportid'. The tables "travel" and "performance" would probably reference 'reportid'. (But keep reading.)
There are places in your diagram where an entity gets an additional key: your company assigns a unique employee id number to its employees, for example. There's no theoretical reason you can't use 'employid' instead of 'partyid' from that point on to reference employees. But there is a practical reason you might not want to do that. It increases the number of joins.
For example, if the tables "credential", "tool", "certification", "academic", and "compliance" referenced employee.employid instead of employee.partyid, you couldn't just join "compliance" and "party" to get the person's name. You'd have to join "employee", too.
Do the other tables such as billing, reporting, credential, etc tables need to have their own respective id's that are primary keys, e.g. billingid, reportingid, credentialid, etc?
They need to have a primary key; the primary key doesn't necessarily have to be an id number. If there's an existing natural key, you have to identify it and declare it UNIQUE anyway.
The table "orders" should probably have only "orderid" as its primary key; use a foreign key reference to identify the customer. In some cases, it makes sense to rename columns. In the case of customers, it might make sense to call its key 'customerid' instead of 'parytid'. I'd create a domain, myself.
create domain PARTY_ID as integer not null;
Then, everywhere that needed a party id number, I'd use the domain instead.
create table customers (
customerid PARTY_ID primary key references parties (partyid),
...
I'd prefer to see a table of managers, too. A reference to it would guarantee that manager.managerid would resolve to an actual manager, not just to any employee.
精彩评论