There's no one-size fits all solution that will tick all of the boxes you want. But one I've seen before is
3) Introduce a base table for items that will share relationships:
CREATE TABLE Entities (
EntityID int not null primary key,
EntityType varchar(10) not null,
constraint CK_EntityTypes CHECK (EntityType in ('Person','Place')),
constraint UQ_Entities_WithTypes UNIQUE (EntityID,EntityType)
)
And then build your People
and Places
tables:
CREATE TABLE People (
PersonID int not null PRIMARY KEY,
EntityType AS CAST('Person' as varchar(10)) persisted,
...Other columns...
constraint FK_People_Entities FOREIGN KEY (PersonID,EntityType) references Entities (EntityID,EntityType)
)
CREATE TABLE Places (
PlaceID int not null PRIMARY KEY,
EntityType AS CAST('Place' as varchar(10)) persisted,
...Other columns...
constraint FK_Places_Entities FOREIGN KEY (PlaceID,EntityType) references Entities (EntityID,EntityType)
)
(I'm not sure Entities
is exactly right when thinking about places - a better name may suggest itself to you).
You can then have Pictures
just references the EntityID
.
Otherwise, if I had to pick between 1 & 2, I'd usually recommend 1. Unless the number of "types" involved gets large, it still doesn't make the Pictures
table too wide, and as you've observed, you can at least use the normal FK mechanisms to enforce cascades, if necessary.
4) If Pictures
is just a very bare table at the moment, maybe query whether there ought to be one pictures table, or one per type. Will pictures of people and pictures of places frequently end up queried together (and even if they are, could a UNION ALL
based query hide the fact that you're using separate tables)?