Q:

Using tableoids as foreign keys in Postgresql

I was wondering whether there was any way possible to reference tableoid's as foreign keys in an inheritance relationship.  For example:
CREATE TABLE employee
(
  name TEXT,
  PRIMARY KEY(name, TABLEOID)
);

CREATE TABLE hourly_employee
(
  hours_worked INT,
  PRIMARY KEY(name)
) INHERITS(employee);

CREATE TABLE salaried_employee
(
  anniversary_date DATE,
  PRIMARY KEY(name)
) INHERITS(employee);

CREATE TABLE employee_training
(
  training_id SERIAL,
  due_date DATE,
  employee_name TEXT,
  emp_oid OID,
  PRIMARY KEY(training_id),
  FOREIGN KEY(employee_name, emp_oid) REFERENCES employee(name, TABLEOID)
);

INSERT INTO hourly_employee (name, hours_worked) VALUES ('Joe Smith', 40);
INSERT INTO salaried_employee(name, anniversary_date) VALUES ('Bob Brown', '2014-02-20');

INSERT INTO employee_training (due_date, employee_name, emp_oid) VALUES ('2016-08-16', 'Bob Brown', 'salaried_employee'::REGCLASS);

In this example, the foreign key is created without a problem, but the last insert will fail with the error Key (employee_name, emp_oid)=(Bob Brown, 16403) is not present in table "employee" even though I can confirm that 16403 is the correct tableoid for salaried_employee.
Is there any way to make this work?

A:

Sadly inheritance has some serious limitations.  Several elements (including unique indexes / foreign keys) only apply to one table and not the children.  Personally I've found it much less useful than I'd have liked it to be.
I know its annoying to suggest you re-design but in my opinion you'd be better to have a single table employee with optional columns instead of the parent / child relations.
CREATE TABLE employee
(
  name TEXT,
  employee_type TEXT,
  hours_worked INT,
  anniversary_date DATE,
  PRIMARY KEY(name, TABLEOID)
);

In the long run you often find the code becomes simpler and frankly much more portable between DBMS as well.
You can ensure the correct fields have been entered for the correct type using constraints to manage which fields are mandatory for each type.
Eg:
ALTER TABLE employee ADD CHECK (
    (type = 'hourly' and hours worked is not null) 
 or (type = 'salaried' and anniversary_date is not null))

