I have entities Workflows, Steps and Fields. They relate to each other like this:
- A
Workflowhas manyStepsandFields. - A
Stephas manyFields.
A Field can belong to either a Workflow or a Step but not to both at once. My first option is to add two foreign key columns to Field where one will always be null. So the fields table will have the following columns:
Fields
- id
- name
- step_id (FK to steps)
- workflow_id (FK to workflows)
This allows to enforce uniqueness of the name in the scope of the parent (by creating a unique index on the parent ID and the name) as well as use foreign key cascading deletes ensuring any time a Workflow or Step is deleted the related Fields will be deleted as well. However, one column is always null and if I introduce another parent of Field in the future it would require adding yet another FK column.
In an attempt to normalize this, I can set up join tables and express the relationship in another way:
Fields
- id
- name
WorkflowFields
- workflow_id (FK to workflows)
- field_id (FK to fields)
StepFields
- step_id (FK to steps)
- field_id (FK to fields)
Now I don't have any null values but I lose the ability to enforce uniqueness and cascade the deletes (when a Workflow or Step is deleted, the join record WorkflowField or StepField will be deleted but not the actual Field record itself).
How do I handle the uniqueness requirement? Should
namebe a column on the join table instead of thefieldstable? This feels wrong but I don't see another way.How do I handle cascading deletes? I want the corresponding
Fieldto be deleted any time theWorkfloworStepor any of the join models are deleted. Are database triggers my only option here?Is there a better alternative or are these the options I'm limited to?