views:

4615

answers:

3

I'm setting up a database using phpMyAdmin. I have two tables (foo and bar), indexed on their primary keys. I am trying to create a relational table (foo_bar) between them, using their primary keys as foreign keys.

I created these tables as MyISAM, but have since changed all three to InnoDB, because I read that MyISAM doesn't support foreign keys. All id fields are INT(11).

When I choose the foo_bar table, click the "relation view" link, and try to set the FK columns to be database.foo.id and database.bar.id, it says "No index defined!" beside each column.

What am I missing?

Clarification/Update

For the sake of simplicity, I want to keep using phpMyAdmin. I am currently using XAMPP, which is easy enough to let me focus on the PHP/CSS/Javascript, and it comes with phpMyAdmin.

Also, although I haven't been able to set up explicit foreign keys yet, I do have a relational table and can perform joins like this:

SELECT * 
FROM foo 
INNER JOIN foo_bar 
ON foo.id = foo_bar.foo_id 
INNER JOIN bar
ON foo_bar.bar_id = bar.id;

It just makes me uncomfortable not to have the FKs explicitly defined in the database.

A: 

I realize that sometimes it's the only option, but I'm not a huge fan of phpMyAdmin. To me it seems limited in its usefulness as an IDE... which of course I suppose one could argue it's not really meant to be.

In any case, I'd recommend installing MySQL Administrator/MySQL Query Browser. If you're on a Windows box (gasp... shame on me I suppose), I think SQL Wave is even better... though their most recent releases I'm less crazy about than the one from about 6 months ago.

codemonkey
So do you think it's throwing an error for no reason in this case?
Nathan Long
i'm going on memory here, but have you tried clicking the edit button on the FK fields to add the indexes in? i.e. i'm wondering if the way the indexes were originally added and/or the changing of the table type may have caused them to be dropped.
codemonkey
Yes, I tried clicking edit, but there's nothing about foreign keys there. It looks like Relations is the place to specify them. Good thought about the index changes, but I already tried indexing the ids of foo and bar again.
Nathan Long
hmm. have you tried recreating the tables using raw DDL (data definition language)? i don't use foreign keys myself... i enforce constraints at stored procedure level. but here's a descent little rundown on writing ddl: http://www.tomjewett.com/dbdesign/dbdesign.php?page=ddldml.php
codemonkey
if phpMyAdmin lets you run an alter table statement directly you might be able to establish the FK's that way.
codemonkey
... to clarify, if you can run an alter statement then you wouldn't need to drop and re-create the tables. you should just be able to alter them to add indexes and/or FK constraints, etc.
codemonkey
+1  A: 

InnoDB allows you to add a new foreign key constraint to a table by using ALTER TABLE:

ALTER TABLE tbl_name
    ADD [CONSTRAINT [symbol]] FOREIGN KEY
    [index_name] (index_col_name, ...)
    REFERENCES tbl_name (index_col_name,...)
    [ON DELETE reference_option]
    [ON UPDATE reference_option]

On the other hand, if MyISAM has advantages over InnoDB in your context, why would you want to create foreign key constraints at all. You can handle this on the model level of your application. Just make sure the columns which you want to use as foreign keys are indexed!

tharkun
Foreign key constraints save me a lot of effort and potential errors. For example, let's say I'm going to delete a user from my system. I could write code that specifies every place in the database where data about that user exists, and tell it to delete it. But I have to keep that delete function up-to-date at all times. On the other hand, if all user-related data has has a FK to the user's ID and is set to cascade on delete, all my code has to say is "delete this user" and the database will take care of deleting everything that has a FK reference to that user. Much cleaner to maintain.
Nathan Long
@Nathan: That's what I'm saying in the post. You can handle that on the model level too. You can implement on delete cascade from the model.
tharkun
+4  A: 

If you want to use phpMyAdmin to set up relations you have to do 2 things. First of all you have to define an index on the foreign key column in the refering table (so foo_bar.foo_id, in your case). Then, go to relation view (in the refering table) and select the refered column (so in your case foo.id) and the on update and on delete actions.

I think foreign keys are really useful if you have multiple tables linked to one another, in particular your delete scripts will become very short if you set the referencing options correctly.

Lex
This was correct. Specifically, on the desired table, you have to go to the "Structure" tab, then look at the bottom for "relation view." On that page, find the correct column and set the "Foreign Key" reference to the primary key of the other table. You can also set options for "on delete" and "on update."
Nathan Long