I have data that kinda looks like this...
Elements
Class | Synthetic ID (pk)
A | 2
A | 3
B | 4
B | 5
C | 6
C | 7
Elements_Xref
ID (pk) | Synthetic ID | Real ID (fk)
. | 2 | 77-8F <--- A class
. | 3 | 30-7D <--- A class
. | 6 | 21-2A <--- C class
. | 7 | 30-7D <--- C class
So I have these elements that are assigned synthetic IDs and are grouped into classes. But these synthetic IDs are then paired with Real ID
s that we actually care about. There is also a constraint that a Real ID
cannot recur in a single class. How can I capture all of this in one coherent design?
I don't want to jam the Real ID
into the upper table because
- It is nullable (there are periods where we don't know what the
Real ID
of something should be). - It's a foreign key to more data.
Obviously this could be done with triggers acting as constraints, but I'm wondering if this could be implemented with regular constraints/unique indexes. Using SQL Server 2005.
I've thought about having two main tables SyntheticByClass
and RealByClass
and then putting IDs of those tables into another xref/link table, but that still doesn't guarantee that the classes of both elements match. Also solvable via trigger.
Edit: This is keyword stuffing but I think it has to do with normalization.
Edit^2: As indicated in the comments below, I seem to have implied that foreign keys cannot be nullable. Which is false, they can! But what cannot be done is setting a unique index on fields where NULLs repeat. Although unique indexes support NULL values, they cannot constraint more than one NULL in a set. Since the Real ID
assignment is initially sparse, multiple NULL Real ID
s per class is more than likely.
Edit^3: Dropped the redundant Elements.ID
column.
Edit^4: General observations. There seems to be three major approaches at work, one of which I already mentioned.
- Triggers. Use a trigger as a constraint to break any data operations that would corrupt the integrity of the data.
- Index a view that joins the tables. Fantastic, I had no idea you could do that with views and indexes.
- Create a multi-column foreign key. Didn't think of doing this, didn't know it was possible. Add the
Class
field to theXref
table. Create a UNIQUE constraint on (Class + Real ID) and a foreign key constraint on (Class + Synthetic ID) back to theElements
table.