Question

I want to propagate the value of a primary key column from a parent table to a specific child table when inserting a new row.

For explanatory purposes I've created following tables:

Create TABLE Material(
MatID serial PRIMARY KEY,
materialname TEXT
);

Create TABLE RealMaterial(
MatID INT REFERENCES Material(MatID),
attributereal TEXT,
PRIMARY KEY(MatID)
);

Create TABLE VirtualMaterial(
MatID INT REFERENCES Material(MatID),
attributevirt TEXT,
PRIMARY KEY(MatID)
);

When I am inserting a new material I automatically want to add either a RealMaterial or a VirtualMaterial (referencing the new ID). I should emphasiZe that I want to use this shared-primary-key pattern and not just single-table-inheritance.

Should I use a trigger for my purposes?

Was it helpful?

Solution

From your comments, it seems that you are not actually concerned with "automatically inserting", but rather with "automatically enforcing" the presence1 and exclusivity2 of children.

Since PostgreSQL supports deferred constraints, you can do it declaratively like this.

However, it requires "uglyfying" your model and generally increases the complexity, so enforcing such constraints at the application level is often considered a lesser evil. You may consider hiding this kind of logic behind an API, to remove the possibility of "rogue" clients bypassing it.


1 For given parent row, there must be a child row. In other words, parent class alone cannot be instantiated - it is abstract.

2 For given parent row, there cannot be more than one child row.

OTHER TIPS

I don't really understand what all of your fields mean and you don't really give a lot of information, but you can possibly accomplish this with an trigger. Again, not lot of information here, so I'm not going to attempt to write a valid example, but a pseudo-code snippet would be:

IF (TG_OP = 'INSERT') THEN
    IF NEW.Parameter = 'REAL' THEN
        INSERT INTO RealMaterial (MatID) VALUES (NEW.MatID);
    ELSE
        INSERT INTO VirtualMaterial (MatID) VALUES (NEW.MatID);
    END IF;
END IF;

I have no idea of the relationship (if any) between Material.Parameter and Parameter2 and Parameter3. Assuming that Material.Parameter controls whether or not a material is real or virtual, then you will need to handle both INSERTS and UPDATES and be able to move the material from "RealMaterial" to "VirtualMaterial" and vice versa. You could probably handle deletes with your Foreign Key (cascade).

Two pieces of unsolicited advice:

  1. When posting, always give as much (relevant) information as you can. It will lead to better answers. Here explaining the relationships would help. Also, you should always include information about what version of PostgreSQL you are using.
  2. From my experience, it feels like you don't need different tables, but one table. I would strongly consider implementing this as a single table.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top