views:

109

answers:

3

Hello all,

I have a database containing a couple tables: files and users. This relationship is many-to-many, so I also have a table called users_files_ref which holds foreign keys to both of the above tables.

Here's the schema of each table:

files -> file_id, file_name

users -> user_id, user_name

users_files_ref -> user_file_ref_id, user_id, file_id

I'm using Codeigniter to build a file host application, and I'm right in the middle of adding the functionality that enables users to upload files. This is where I'm running into my problem.

Once I add a file to the files table, I will need that new file's id to update the users_files_ref table. Right now I'm adding the record to the files table, and then I imagined I'd run a query to grab the last file added, so that I can get the ID, and then use that ID to insert the new users_files_ref record.

I know this will work on a small scale, but I imagine there is a better way of managing these records, especially in a heavy-traffic scenario.

I am new to relational database stuff but have been around PHP for a while, so please bear with me here :-)

I have primary and foreign keys set up correctly for the files, users, and users_files_ref tables, I'm just wondering how to manage the adding of file records for this scenario?

Thanks for any help provided, it's much appreciated.

-Wes

A: 

I think what you need is just this:

                   ----primary key-----
users_files_ref -> | user_id, file_id |

How you get the the file_id is dependent on the code you're implementing. Your reasoning is correct. You already have the user_id and just need to get the file_id. With these values you can add a new row to user_files_ref.

When I need to do this I usually have a stored procedure with the help of a sequence that inserts the file and returns the sequence NEXTVAL as the output. This might be a way of implementing such cenario.

This is the code for an Oracle based stored procedure:

CREATE OR REPLACE PROCEDURE SP_IMPORT_FILE(FILE    IN  FILE.FILE%TYPE,
                                           FILE_ID OUT NUMBER)

IS

BEGIN

  SELECT SEQ_FILE.NEXTVAL INTO FILE_ID from DUAL;

  INSERT INTO FILE (FILE_ID, FILE) VALUES (FILE_ID, FILE);

END SP_IMPORT_FILE;
Leniel Macaferi
Thanks very much Leniel! It looks like I could use a stored procedure for creating a default folder record for each user as they are created as well, so this looks very useful, I'm definitely going to do some research stored procedures. Thanks again for sharing!
wes
A: 

You're basically describing how it normally is done, with one important adjustment: how you retrieve the file_id of the file to be able to add it to users_files_ref.

Normally in a database environment you have many clients connecting at the same time, doing updates simultaneously. In such an environment you can't just get the file_id of the last file added - it might be someone elses file added in between your DB calls. You have to use functionality of the database to get the ID generated (e.g. SELECT @@IDENTITY on MSSQL) or generate the IDs in the application code somehow.

Anders Abel
I think for now I'll go with a stored procedure if I can wrap my head around those quickly, since that way I can just let the database worry about creating the IDs for me. I do want to accommodate a high traffic situation if one occurs tho. The poster below, Summer, just made me aware of a function in PHP that will grab the last inserted ID, which is much easier for me since I wouldn't have to learn stored procedures. But I'm wondering if issues arise under high volume traffic? If you have any experience here I'd love to hear any tips you might have. Thanks for your input Anders!
wes
A: 

Use $this->db->insert_id() to get the id number of the row you just inserted. Further documentation here: http://codeigniter.com/user_guide/database/helpers.html

Summer
Summer, I crossed this when looking over the CI documentation and just didn't notice that it actually grabbed the last insert (d'oh!) :]This looks like the perfect solution, since no stored procedure learning is required, but I'm wondering if stored procedures can manage the integrity of these inserts better during times when many users are uploading simultaneously. Have you ever run into trouble with this particular method? Thanks for bringing this little gem to my attention!
wes
I bet the folks at Ellis Labs are too good to expose a database method with obvious concurrency problems. Or, you can always look at the source code to reassure yourself. I've never had problems. :)
Summer