Hello Jan,

On 1/7/2012 00:58, Jan Steinman wrote:
Okay, I'm seeking enlightenment here.

In my trivial case, one can save storage by not having a record extension for 
people without phones. Big deal.

In my real-world case, I have a contacts database with your typical name, address, phone, email, etc. info. 
Then I have extensions for people who are particular type of contacts that have more information than the 
general case. If I have several thousand records in my contacts database, but only ten in the "dairy 
customers" database, I'm saving a ton of storage by not having every single record in the 
general-purpose contacts database contain stuff like "desired_milk_pickup_day" or SET 
"dairy_products_of_interest".

But now I have a different extension, "Volunteers", with extra fields like "special_skills", 
"dietary_restrictions", etc. I don't want those fields in the general contact list. And there's another 
extension, "Advisory", that holds extra information for contacts who are on our advisory council.

In normalizing databases, I was taught to do exactly what I've done, separate 
out the special cases and put them in a separate table. But as you note, that 
creates a bit of a mess for INSERT while simplifying SELECT.

ON UPDATE CLAUSE does not help on INSERT, does it? I mean, how does it know the 
auto-increment value of the parent record before it's been INSERTed?

It appears that anything I do must be wrapped in a transaction, or there's the 
chance (however unlikely) that something will get in between the INSERT of the 
parent and that of the child.


Once you have inserted the 'parent' row (the one to the Contacts table) you know the ID of the parent. This cannot change and no other contacts will be given the same ID. You include this ID with the other INSERT commands you need for your 'child' rows.

You do have two options to handle rollback scenarios:
1) run with only InnoDB tables and wrap all of the related INSERTs with a single transaction

2) use any tables you like and keep track of the auto_increment values issued for each row you are INSERTING in your application, too. This allows you to implement a manual rollback in the event of some kind of problem.

Take, for example, your Volunteers example. This requires at least two rows: one main row on the `contacts` table and another on the `volunteers` table.

  INSERT `contacts` (name, ...) VALUES ('Bob the Volunteer',...);
  SET @contact_id = LAST_INSERT_ID();
INSERT `volunteers` (contact_id, skill, diet_restrict, ...) VALUES (@contact_id, 'carpentry', 'hates fish', ...);
  SET @volunteer_id = LAST_INSERT_ID();
  ...

If you don't want to track the ID values in user variables, you can query them and draw them back into application-based variables. If you want to track lists of values, you can add them to temporary tables to build each list or query them into application-side arrays. At this point how you handle those numbers is up to you.

Remember, though, that LAST_INSERT_ID() can only return one value. This means that you cannot use it for batch processing reliably unless you manually lock the table and guarantee a specific sequence of numbers. The other option is to build an association table of (id, name) based on the newly-inserted data (or something similar based on some unique combination of identifiers in your original data instead of just 'name' ) so that each of your child rows can be assigned their proper parent id values.
http://dev.mysql.com/doc/refman/5.5/en/information-functions.html#function_last-insert-id

--
Shawn Green
MySQL Principal Technical Support Engineer
Oracle USA, Inc. - Hardware and Software, Engineered to Work Together.
Office: Blountville, TN

--
MySQL General Mailing List
For list archives: http://lists.mysql.com/mysql
To unsubscribe:    http://lists.mysql.com/mysql

Reply via email to