views:

178

answers:

2

I am making a database for a program where i am supposed to model some relations in the family. ex: X is father to Y , Y is son to X

So , i have a Members table with all info about each member so i thought about making a many to many relation between the Members table and itself so that the Member_Member bridge table will be having the columns "FK_FromID , FK_ToID" as composite key (is this correct ?) and "FK_RelationType" as a foreign key to RelationTypes table which will have the relation type "Father,mother, son,daughter" , and two relations going as one to many from the Members table to these two foreign keys

My problem is : when deleting if i choose cascading then i will make cycles because if i delete a member then there will be two delete passes to related records in Member_Member bridge , knowing that in the program whenever i insert a father relation i will insert a son relation as well in the Member_Member table , is there a way or a workaround possible to enable cascading so that whenever i delete a member i will delete the related records in Member_member regardless of being recorded in either a to or a from foreign key column

So, i don't know what to do , is this a correct design in the first place or what ? , what should i do about cycling , also what do you think a better design for the same problem should be knowing that i need to specify what kind of relation between the two parties

Thanks a lot for any help , and sorry for bad english Bishoy

+2  A: 

SQL does not handle "network" problems like this very well.

The member-member bridge table is a terrible name. It's a "member-parent" (or "parent-child") bridge. Bridge tables should not have a "composite key". Bridge tables have a surrogate key (just a sequential number) and a pair of FK references to other tables. The two FK's should have names like "member" and "parent" to make it perfectly clear what the relationship is in this table.

Everyone has a parent. Not everyone has children. Some parents will not have parents in this database; they're the "top parents".

It's easiest if the top parents have rows in the parent-child bridge with a parent FK of NULL. That way you avoid super-complex outer-joins -- every member has at least one member-parent row; ideally two.

You will find many "cycling" issues since relationships are transitive.

Note that you can't -- in a single standard SQL query -- find all members of the family, or all parents back to the top of the family, or all children and grand-children. There are SQL extensions that make this possible, but the standard doesn't handle it well.

The cascading delete doesn't work out well because the relationships in a family are directed in two ways (parent to children, child to parents), but SQL only has one kind of direction (FK reference).

You can try to assure that every member MUST have at least one (and at most two) rows in "member-parent" and the delete of a member deletes the two rows in "member-parent" and the keys have the proper names, you might make parts of this work.

Note that when you delete a member, this will break their parent relationships. You delete the member-parent row. That's good. What about their children? The other rows which have member-parent referring to this deleted parent are now broken. What does this mean? What should be done?

There's no standard answer. Removing rows from a connected graph leaves elements unconnected. You have to work out some sensible rules for that.

Since SQL does not do this well, all designs will seem to have problems.

S.Lott
+1 becuase I agree with most of this. I disagree that *Bridge tables should not have a "composite key".* A surrogate primary key is only necessary if the bridge table has attributes of its own, or is referenced in foreign keys. And even then the composite key should be enforced as a unique key.
APC
@APC: If you're ever going to use an ORM, you're going to need surrogate keys. Once you take that step, composite keys are a needless complication. Just create an index for performance and be done with it.
S.Lott
Surrogate keys do not enforce relational integrity. They are useful devices but we still ought to enforce the *business keys*, whether single column or multiple columns. Now many people are comfortable with the idea of the application enforcing data integrity but I'm not one of them. Besides the questioner was asking about database design not ORM, so I think my observation remains valid.
APC
@APC: Surrogate keys don't enforce integrity? Really? Why not? What's a "business key"? A piece of data that can change because it was spelled wrong, which will in turn trigger a cascade of changes?
S.Lott
I can't help feeling that this is exceeding the scope of a comments thread. Anyway. A surrogate key is a meaningless identifier; a business key is an identifier of something unique in the real world. But you're right, business keys can change, that's why surrogate keys are useful. Cast iron example: email addreses are unique but users will want to change the one associated with their account. So, to avoid that cascading (and other complications) we have a surrogate user id (number). But we still want to enforce the uniqueness of an email in the Accounts table. Don't we???
APC
@APC: uniqueness is different from being a formal key. That can be done with a unique index. My point remains that too many things are called "keys" and it leads to trouble. The first place is with ORM. Other places show up as problems also. My universal advice is stick to surrogate keys and for things that have to be unique, add a unique index. Surrogate keys are simpler and harder to break. Composite keys are almost always a bad idea; a simple unique index on the field pair is better.
S.Lott
Well , thanks for all help , i will use Entity framework as my ORM , but i can't get why composite key will complicate it ? .Also , if i need a family record i can put some foreign key in the bridge table to a new table family and then i can get the whole family in one SQL statement (is this correct ?) .and about insuring that when i delete a parent i will also delete the child , can i make a trigger to look for all it's records where it is a child and delete it from the bridge table as well ?Sorry for too much of questions
Bashawy
@Bashawy: A composite key *is* more complex than a surrogate key. "Family Record"? Transitive fetch of all children of a single parent? Yes, you can make the bridge table do this. Yes, you can add complex triggers to implement whatever rules you make up.
S.Lott
A: 
  1. Assuming each member can only have one mother and one father, you would be able to derive all the relationships by simply keeping a mother_id and father_id field in the members table.

    However this would only work if your database will not have missing information. For example, if member X is the brother of member Y, there would be no way to know this unless the parents of X and Y are stored in the database.

    If your database will not be having missing information, the above might be easier to manage data integrity. Queries might get a bit complex however.

  2. The member_member bridge you suggested has one serious problem since it implies a direction of the relationship, so that if X is the father of Y, Y is also the son of X. You suggested to define the relationship twice in both directions, but in general this is not recommended. This is a form of data duplication, and you can struggle to enforce referential integrity with duplication of data. Remember that the DBMS does not know that X is father of Y is the same as Y is the son of X.

I am aware that this is not a complete answer, but just a few observations. I totally agree with S.Lott's answer as in there is no standard way to "solve" this with relational databases.

Daniel Vassallo
Thanks a lot for your answer , really appreciate it
Bashawy