Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a foreign key have a constant instead of a field name? Relate FK to STI subclass

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?

like image 437
Shadow Radiance Avatar asked Nov 25 '12 13:11

Shadow Radiance


1 Answers

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.

like image 67
Bill Karwin Avatar answered Oct 22 '22 03:10

Bill Karwin