Friday, June 15, 2018

MySQL conditional referencing of foreign key

Leave a Comment

I'm currently working on a schema with nullable foreign key. Basically, this is what I want to achieve:

Given:

table 1:

game:   id   observer_id   starts_on   ends_on   type 

table 2:

observer:   id   game_id DEFAULT NULL   starts_on   ends_on   type   FOREIGN KEY (`game_id`) REFERENCES `game`(`id`) ON DELETE SET NULL 

Now, what I want to do - I want to duplicate as the initial values and update on cascade starts_on, ends_on and type fields in observer table if I have a reference to a game, however if game_id is null I want to have an independent values for above mentioned fields. Is something like this possible with IF in mysql or should I implement the logic in my model files?

2 Answers

Answers 1

Consider to solve your issue while data retrieving (SELECT) instead of data manipulation (INSERT/UPDATE/DELETE).

select     o.id,     o.game_id,     coalesce(g.starts_on, o.starts_on) as starts_on,     coalesce(g.ends_on,   o.ends_on)   as ends_on,     coalesce(g.type,      o.type)      as type from observer o left join game g on g.id = o.game_id 

In this query if o.game_id is NULL the LEFT JOIN will find no matches in the game table and all its columns will also be NULL. Then COALESCE() will take care of choosing the value from the game table if present or from observer otherwise.

You can use that query in a VIEW (if you like), but i can't tell if it will perform well in any use case.

This way you can store your "independent" values without worrying if the game id is set or not, since they will only be used, if the game_id is not NULL.

Note that your problem might be solved in a more "clean" way changing the schema. With the columns game.observer_id and observer.game_id it looks like a cyclic relation, which can be considered as "design smell". But without knowledge of your data logic I can't suggest a better way.

Answers 2

FOREIGN KEYs do a limited number of things. Once you go beyond them, you should build your own transaction in your app code (or Stored Procedure or ...) to do the more complex things.

I feel that this is the safer route, since you know exactly what you need, and won't have to try to shoehorn FKs into doing it.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment