Welcome to the dBforums forums.

You are currently viewing our boards as a guest which gives you limited access to view most discussions, articles and access our other FREE features. By joining our free community you will have access to post topics, communicate privately with other members (PM), respond to polls, upload your own photos and access many other special features. Registration is fast, simple and absolutely free so please, join our community today!

If you have any problems with the registration process or your account login, please contact contact support.

If you prefer not to see double-underlined words and corresponding ads, place your cursor
here for ContentLink opt out.

Go Back  dBforums > General > Database Concepts & Design > Referential Integrity Problem

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old 09-12-07, 08:30
littlecharva littlecharva is offline
Registered User
 
Join Date: Sep 2007
Posts: 6
Referential Integrity Problem

Hi,

Say I have a few tables for collecting different kinds of records in my DB:

Customer
ID, Name, Address, Postcode

Client
ID, Name

Property
ID, Address, CreationDate

Now each of these tables have a web form to allow the user to edit records, and on each of those web forms, I want to provide the user the ability to log a message, so I have a table such as:

Message
ID, Table, Reference, Message, CreationDate

Where Table contains the Table that stores the related record, and Reference contains the relevant ID. So if I were displaying the Property with ID = 3, I could do a:

SELECT Message FROM Message WHERE Table = 'Property' AND ID = 3

To get all related Messages. Works fine.

The problem I have is with referential integrity. If I delete Property #3, I want the Messages to be deleted too. Likewise with Customer and Client. How can I acheive this?

Thanks,
Anthony Burns
Reply With Quote
  #2 (permalink)  
Old 09-12-07, 09:00
andrewst andrewst is offline
Moderator.
 
Join Date: Sep 2002
Location: UK
Posts: 4,874
You can't use ON DELETE CASCADE because of the generic nature of your Messages table. Depending on your DBMS you could perhaps write a database trigger to do the job, or allow deletions only via a stored procedure (API) that deletes the messages as well. Alternatively you could just let the messages become "orphans" and write a periodic batch job to purge them.
__________________
Tony Andrews
http://tonyandrews.blogspot.com
Reply With Quote
  #3 (permalink)  
Old 09-12-07, 09:02
littlecharva littlecharva is offline
Registered User
 
Join Date: Sep 2007
Posts: 6
I would imagine this to be a reasonably common (or certainly not rare) design problem. Is there not a design pattern about to deal with these sorts of things?

Am I designing my database the wrong way? Is there a better way to acheive the functionality I require?

Anthony
Reply With Quote
  #4 (permalink)  
Old 09-12-07, 09:52
andrewst andrewst is offline
Moderator.
 
Join Date: Sep 2002
Location: UK
Posts: 4,874
Well, you could create a message table per entity type: customer_message, client_message, ... Then standard RI could implement the cascade delete. Apart from creating a few more tables, does this have any drawbacks for you?

I have seen both ways done, but nothing as grand as a "design pattern"!
__________________
Tony Andrews
http://tonyandrews.blogspot.com
Reply With Quote
  #5 (permalink)  
Old 09-12-07, 09:58
georgev georgev is offline
SQL Apprentice
 
Join Date: Jan 2007
Location: hiding
Posts: 8,143
This looks suspiciously like the impementation of a OTLT (One True Lookup Table)!

I'm afraid Andrewst is right - because of your structure you cannot simply use cascading.

One possible solution would be to have a NotesID in each of your tables which is the foreign key reference to the Messages table. However, this (in theory) makes your messages table the parent to the others... Hmmm
__________________
George
You only stop learning when you stop asking questions.
Reply With Quote
  #6 (permalink)  
Old 09-12-07, 10:21
aschk aschk is offline
Registered User
 
Join Date: Mar 2007
Location: 636f6d7075746572
Posts: 734
Going by some simple logic here I would say that the notes that are being added are specific to whichever section they're in.
i.e.
The program user is in the client section (editing client info), and thus ANY notes they should be adding ought to be related to the section they're in (clients).

Think about it, why would you write a note about a customer in the client section? They're separate things.

Thus it would seem logic that you have client_notes, customer_notes, and property_notes, that are SPECIFIC to their section only. Bring forth your referential key...
Reply With Quote
  #7 (permalink)  
Old 09-12-07, 10:25
littlecharva littlecharva is offline
Registered User
 
Join Date: Sep 2007
Posts: 6
Surely un-necessary duplication like that is bad design? When I want to make a change to my table structure I have to make that change to multiple tables, and if I want to query all messages logged by an individual I have to join all tables together. And then if I add a new table that requires me to add another xxx_Message table, I then have to update all my other stuff to incorporate the new message table.

I guess I'll have to go without referential integrity and live with the orphans.

Thanks for your advice anyway though, at least I know my options.

Oh, the poor orphans.

Anthony
Reply With Quote
  #8 (permalink)  
Old 09-12-07, 11:47
andrewst andrewst is offline
Moderator.
 
Join Date: Sep 2002
Location: UK
Posts: 4,874
Quote:
Originally Posted by littlecharva
Surely un-necessary duplication like that is bad design? When I want to make a change to my table structure I have to make that change to multiple tables, and if I want to query all messages logged by an individual I have to join all tables together. And then if I add a new table that requires me to add another xxx_Message table, I then have to update all my other stuff to incorporate the new message table.
Well, it is necessary duplication (of structure, not of data) if you want to use regular SQL RI constraints to perform the cascade delete. Whether it is bad design depends on how many of these tables there will be, how much they really change, how well it performs, how hard it is to maintain the code etc. There are trade-offs involved, and you need to weigh these up.
__________________
Tony Andrews
http://tonyandrews.blogspot.com
Reply With Quote
  #9 (permalink)  
Old 09-12-07, 11:56
r937 r937 is offline
SQL Consultant
 
Join Date: Apr 2002
Location: Toronto, Canada
Posts: 13,556
Quote:
Originally Posted by littlecharva
Am I designing my database the wrong way?
yes

any time you store meta data -- such as a table name -- you are making a design error

when you do this --
Quote:
Message
ID, Table, Reference, Message, CreationDate

Where Table contains the Table that stores the related record, and Reference contains the relevant ID.
it becomes impossible to define the Reference FK, therefore you are not assured of RI
__________________
r937.com | rudy.ca

pre-order my book Simply SQL from Amazon
Reply With Quote
  #10 (permalink)  
Old 09-12-07, 12:15
littlecharva littlecharva is offline
Registered User
 
Join Date: Sep 2007
Posts: 6
georgev: Are you suggesting something like:

Client
ID, MessageID, Name
01, 56, Bill Jones

Message
ID, Message
56, Bill is Dead

? That would only allow me one message per record though, and I need more.

R937: That's exactly my point. Having only one Message table prohibits me from using RI, but having a Message table for each of the main tables (possibly 15+) becomes a maintenance nightmare.

aschk: I see your point, but the structure of the tables would be identical, there could be in excess of 15 message tables, and I would want to provide an inbox style page where a user could view all of their messages in one place, which would involve multiple joins and having to update that code each time I added a new table.

andrewst: It is a trade-off you're right, I was just hoping there was going to be an easy answer.

Anthony
Reply With Quote
  #11 (permalink)  
Old 09-12-07, 12:21
r937 r937 is offline
SQL Consultant
 
Join Date: Apr 2002
Location: Toronto, Canada
Posts: 13,556
nobody said you have to have 15 message tables

i would agree that one message table is better

it is "linking" a message to one of 15 different tables that is the design challenge

here's a step in the right direction: suppose your message table had 15 foreign keys, each of them nullable (since on any given row, 14 of the 15 will actually be null)

then you could define proper FKs and actually have the database enforce them
__________________
r937.com | rudy.ca

pre-order my book Simply SQL from Amazon
Reply With Quote
  #12 (permalink)  
Old 09-12-07, 13:03
littlecharva littlecharva is offline
Registered User
 
Join Date: Sep 2007
Posts: 6
I like your thinking, but feel like having so many null fields is a bad design too. How about having a linking table for each section such as:

Client
ID,Name
54,Bill

Message
ID,Message
98,Do stuff

Client_Message
ClientID,MessageID
54,98

That would enable me to retain RI yeah? And although I would essentially have a lookup table for each main table, I wouldn't be duplicating the message structure and I'd still be keeping my messages stored together. How does that strike people?

Also, back to the Meta data thing. I'd also still want to keep a record in the Message table as to what the message is related to for my application's benefit, so I'd still be storing stuff like:

ID,Relation,Message
98,Client,Do stuff

So when I listed the messages in an inbox, I could then provide a link the the Client page along with it. Is this still a no-no?

Anthony
Reply With Quote
  #13 (permalink)  
Old 09-12-07, 13:33
r937 r937 is offline
SQL Consultant
 
Join Date: Apr 2002
Location: Toronto, Canada
Posts: 13,556
Quote:
Originally Posted by littlecharva
How about having a linking table for each section
you prefer 15 linking tables to one table with 15 nullable Fks?
__________________
r937.com | rudy.ca

pre-order my book Simply SQL from Amazon
Reply With Quote
  #14 (permalink)  
Old 09-17-07, 13:28
littlecharva littlecharva is offline
Registered User
 
Join Date: Sep 2007
Posts: 6
Not really, I dislike both to be honest. I just wish there was a more elegant solution.

Thanks for all the help anyway though.
Reply With Quote
  #15 (permalink)  
Old 09-17-07, 13:43
r937 r937 is offline
SQL Consultant
 
Join Date: Apr 2002
Location: Toronto, Canada
Posts: 13,556
elegant?

look, in post #1 you mention 4 tables, and each one of them has a column called ID

isn't that also inelegant? how come you aren't also looking to find a way to combine them?
__________________
r937.com | rudy.ca

pre-order my book Simply SQL from Amazon
Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On