views:

397

answers:

5

Scenario

I have 3 database tables. One is for Images and the other two are People & Places. Since each person can have many images and each place can have many images, I want to have a ONE TO MANY Relationship between both people and images, as well as places and images.

Question

Does the foreign key have to be called the same name as the primary key? Or is it possible for me to call the Foreign key in the images table something generic, for example "PKTableID". This way I only need one image table.

Help greatly appreciated.

Regards,

EDIT:

The reason for wanting to have only a single image table, is because each image only refers to a single other table. As well as this, I used the example here of two tables, the actually database I will be using will have 20 tables, so I wanted to know whether it was still possible to use a SINGLE IMAGE TABLE FOR 20 ONE-TO-MANY RELATIONSHIPS?

+5  A: 

EDIT

If one image is only ever owned by one of the twenty tables, this design might work:

People (PersonId, Name)
Places (PlaceId, Name)
Dogs (DogId, Breed)
Doors (DoorId, Height, Width)
Images (ImageId, ImageBinary, OwnerId, OwnerTable)

Where OwnerTable is the name or the code for the table that OwnerId belongs to.

This would save you 20 FKs in the image table, or 20 association tables. Then, in the joins, you would specify OwnerTable, depending on the table you are joining to.

You would need to use convertable types for the Ids (eg, TINYINT, SMALLINT, and INT), and preferably one type for all (eg, INT), and you would have to manage referential integrity yourself though triggers or some other code.

/EDIT

You need 5 tables, not 3:

People (PersonId, Name)
Places (PlaceId, Name)
Images (ImageId, ImageBinary)
ImagesPeople (ImageId, PersonId)
ImagesPlaces (ImageId, PlaceId)

You can call the fields whatever you want. People.Id, ImagesPeople.PersonId, etc.

But what you can't do is something like this:

People (PersonId, Name)
Places (PlaceId, Name)
Images (ImageId, ImageBinary, PlaceOrPersonId)

Well, you can, but the database won't help you enforce the relationship, or tell you which table the FK belongs to. How would you know? There are hackish work-arounds like staggering the id increments, adding a type column to Images, or using GUIDs.

Alternatively:

Things (ThingId PK, Type)
People (ThingId PK/FK, Name, Age)
Places (ThingId PK/FK, Name, LatLon)
Images (ImageId PK, ImageBinary, ThingId FK)

You could also make Images a "Thing". Sometimes you see designs like this. It does give you referential integrity, but not type exclusivity. You could have the same ThingId in People, Places and Images, and the database wouldn't care. You would have to code that rule yourself.

Edit: at Cylon Cat's suggestion, scenario 4:

People (PersonId, Name)
Places (PlaceId, Name)
PeopleImages (PeopleImageId, ImageBinary)
PlaceImages (PlaceImageId, ImageBinary)

Here, images are exclusively owned by one person or place. Similar to version 2, but with declared foreign keys. It may have some performance benefits vs the 5 table design, since fewer joins are required. You lose "Image" as a distinct entity, replaced by "PeopleImage" and "PlaceImage".

Peter
I agree. I generally end my mapping table with "mapping" (Ex: "ImagesPlacesMapping") But I could understand arguments against doing it that way.
JoshBaltzell
Oh, these were just made-up names, to communicate an idea, not necessarily what I'd use in the database. I find good names agonizingly difficult.
Peter
@Josh: I use XREF. IE: `IMAGES_PEOPLE_XREF`, `IMAGES_PLACES_XREF`
OMG Ponies
I think you misread the question. The 5 table structure is needed only for MANY TO MANY relationship, but the question is about ONE TO MANY. Junction tables are necessary only for many to many relationships. 4 tables suffice for one to many with enforced FK relationships: People, Places, PeopleImages, and PlaceImages.
Cylon Cat
@Cylon Cat: that depends on whether he wants to images to be shared between people and/or places, or if they are exclusively owned. Imagine facebook-style tagging, for example.
Peter
Hi all, thankyou for the input. I have added an edit to my question. Also, I'm quite confused, ARE YOU ALL SAYING THAT A SINGLE IMAGE TABLE WILL NOT WORK? - Due to the fact that the image table won't know which table the foreign key relates too......unless I use GUIDs, which I really don't want to use....
Goober
A single image table w/ association tables might work, but you would have to manage referential integrity yourself, and add a foreign key type column to the images table, and ensure all the Ids are the same type (or at least a convertible type).
Peter
I think this is the answer. The question does not have a single "correct" answer, but this gives several viable options.
JoshBaltzell
+1  A: 

As Peter pointed out you really need a many to many relationship, unless you want to restrict your images to pictures with only one person, also, a good place index will reflect the hierarchical nature of place names (Montmartre, Paris, France = three possible names for one place).

Now technically you can call your indexes and tables anything that is not a reserved word and has not been used already, X, Y , Z12345 and WOBBLY are all valid names for an index.

In practice however its best to follow a naming convention that points to whats being stored and what for. So tables PEOPLE_X_IMAGES and a PLACES_X_IMAGES would be a good idea in your case. You dont really need anything about people or places in the actual images table. Likewise you dont need anything about images in the PEOPLE and PLACES tables.

James Anderson
A: 

You can use one table but you would need twenty different fields for the relationships. If you set up a foreign key relationship, then all the data must relate to the parent table, you can't store two foreign key relationships in one table. So you must set up a column for each fk you want to have.

HLGEM
+1  A: 

You could add theoretically add two foreign keys to the images table, one for People and one for Places. Then you could allow nulls and join on the appropriate columns when running a query. This is not much of a solution though because what does this table look like when you have 14 tables that need to join with it?

If you are not going to use GUIDs, then I say you set it up as many-to-many for the sake of the next guy that has to understand it.

JoshBaltzell
Sorry, @HLGEM beat me to basically the same answer by a couple of seconds.
JoshBaltzell
A: 

How about

Person (PersonId PK, Name, ImageId FK)
Image (ImageId PK, Name)
Place (PlaceId PK, Name, ImageId FK)
Kamal
Thats definately not correct...
Goober
This is one-to-many, but it is backwards. This would allow one Image to have many people, not one person to have many images.
JoshBaltzell
noted..........
Kamal