views:

89

answers:

3

I want to start by saying that I am a big fan of using foreign keys and have a tendency to use them even on small projects to keep my database from being filled with orphaned data. On larger projects I end up with gobs of keys which end up covering upwards of 8 - 10 layers of data.

I want to know if anyone could suggest a graceful way of handling 'expected errors' from the MySQL database in a way that I can construct meaningful messages for the end user. I will explain 'expected errors' with an example.

Lets say I have a set of tables used for basic discussions:

discussion
questions
responses
users

Hierarchically they would probably look something like this:

-users
--discussion
---questions
----responses

When I attempt to delete a user the FKs will check discussions and if any discussion exist the deletion is restricted, deleting discussion checks questions, deleting questions checks responses. An 'expected error' in this case would be attempting to delete a user--unless they are newly created I can anticipate that one or more foreign keys will fail causing an error.

What I WANT to do is to catch that error on deletion and be able to tell the end user something like 'We're sorry, but all discussions must be removed before you can delete this user...'.

Now I know I can keep and maintain matching arrays in PHP and map specific errors to messages but that is messy and prone to becoming stagnant, or I could manually run a set of selects prior to attempting the deletion, but then I am doing just as much work as without using FKs.

Any help here would be greatly appreciated, or if I am just looking at this completely wrong then please let me know.

On a side note I generally use CodeIgniter for my application development, so if that would open up an avenue through that framework please consider that in your answers.

Thanks in Advance

A: 

Sounds like you need to define your foreign keys with ON DELETE CASCADE. This will delete any referenced data in other tables.

Kenaniah
In this case I do NOT want the data to cascade--my example was fairly inane because I wanted to keep it simple but in some cases I want it to fail but I need to let the user know why. Thanks though!
angryCodeMonkey
A: 

You shouldn't be relying on the database to create errors for your application code. the FK's are there for when your app code messes up and tries to delete something it shouldn't.

If you really want to give the user a nice error message you will have to run the selects first, and build the appropriate error message.

edit

You can check for foreign keys in one select. If you are using an ORM like doctrine, you don't even have to specify the join, just tell it what fields to select, then check each table for nonzero rows.

Byron Whitlock
I agree that FKs can act as a safety net for an application, but I don't think that is the only use for them--the way I read your post you would not use FKs to cascade delete data to remove orphans but would instead do that manually in code? I think FK's can be used to automate a LOT of data handling we do in code and since I am doing it anyway I just want to build on that from the code side.
angryCodeMonkey
I'll take a look at Doctrine and see how that works--I have never seen someone 'ping' an FK through a select, that would be very handy though.
angryCodeMonkey
+2  A: 

Sadly, MySQL does not expose the ability to define a custom error like you would with SQL Server or Oracle.

Workaround


Check this blog post about using a UDF to be able to define custom errors.

OMG Ponies
Those are some very interesting links, thank you! If I am reading it correctly it looks like 5.5 will include SIGNAL and RESIGNAL for SPs but probably no way to call them from a general DELETE failure. SO CLOSE, but so far away. Again it would force me to re-write all of my FK rules in triggers or SPs instead of using an existing functionality. Still great information though!
angryCodeMonkey
@Shane: Incidentally - Postgres does have the ability to trap errors: http://www.postgresql.org/docs/8.4/static/plpgsql-errors-and-messages.html
OMG Ponies
@OMG Ponies - Not to knock MySQL (I use it almost every day all day long) but this is the first time in 10 years I have really 'felt' that that something was lacking. Not a big deal, but a little painful. =)
angryCodeMonkey
@Shane: Not so much 10 years, but if that's your first MySQL shortcoming you haven't looked at using analytic functions, CTE support, and views.
OMG Ponies
@OMG Ponies - You are right on all counts--haven't really found a need for most, though I have tried views but couldn't find a good use case for them (possibly because of some underlying issue with them that I was unaware of at the time).
angryCodeMonkey