TalkPHP
 
 
Account Login
Latest Articles
» The basic usage of PHPTAL, a XML/XHTML template library for PHP
» Vulnerable methods and the areas they are commonly trusted in.
» Simple way to protect a form from bot
» The Basics On: How Session Stealing Works
» How to keep your forms from double posting data
Advertisement
Associates
Associates
techtuts Darkmindz
CSS Tutorials Tutorialsphere.com - Free Online Tutorials
Boston PHP SurfnLearn
Reply
 
LinkBack Thread Tools Display Modes
Old 01-31-2008, 11:39 AM   #1 (permalink)
The Frequenter
 
Join Date: Dec 2007
Location: In my basement
Posts: 368
Thanks: 44
Aaron is on a distinguished road
Default What is good MySQL practice?

With all these joins and fancy things, it makes me wonder; what is good MySql practice? I thought that you could just list everything in a row, but no one here seems to do that.
Send a message via MSN to Aaron
Aaron is offline  
Reply With Quote
Old 01-31-2008, 12:55 PM   #2 (permalink)
The Contributor
 
buggabill's Avatar
 
Join Date: Jan 2008
Location: Maine, USA
Posts: 92
Thanks: 2
buggabill is on a distinguished road
Default

Hi Aaron,

Quote:
With all these joins and fancy things, it makes me wonder; what is good MySql practice?
Good MySQL practice is as little redundancy in the tables as possible, optimized queries, getting only what you need... There are numerous books written on best practices for MySQL. Is there something specific that you are thinking about?

Quote:
I thought that you could just list everything in a row, but no one here seems to do that.
What do you mean list everything in a row?
__________________
-- Bill
"Why is it drug addicts and computer aficionados are both called users?" -Clifford Stoll
buggabill is offline  
Reply With Quote
Old 01-31-2008, 03:13 PM   #3 (permalink)
The Gregarious
Top Contributor 
 
Village Idiot's Avatar
 
Join Date: Sep 2007
Posts: 566
Thanks: 15
Village Idiot is on a distinguished road
Default

Theoretically, you could put all the data on one row, but that would make it so hard to maintain it would become inefficient. Plus not all data can be extracted in the same way (row count differences). All good coding is a battle between efficiency, shortness and readability.
__________________
There are two ways to write bug-free code, only the third one works.
Village Idiot is offline  
Reply With Quote
Old 01-31-2008, 05:46 PM   #4 (permalink)
The Contributor
 
DeMo's Avatar
 
Join Date: Jan 2008
Location: Brazil
Posts: 77
Thanks: 14
DeMo is on a distinguished road
Default

Hi Aaron, relational databases (like MySQL) have this name because you can create relations between the table. The types of relations are one-to-one, one-to-many/many-to-one and many-to-many.

Quote:
I thought that you could just list everything in a row
That depends on the case, and this is where the relations between tables come in.

Let me give you a simple example, suppose you are creating a simple contact application where you can store your friend's name, address, phone numbers and emails. We will also suppose that each contact can have 3 phone numbers and 2 e-mail addresses, your table would look like this:
Code:
------------
|contacts  |
------------
|contact_id|
|name      |
|address   |
|phone1    |
|phone2    |
|phone3    |
|email1    |
|email2    |
------------
What we did here is what you said: we listed everything in a row.
Now with this design we have 2 main issues:
  1. Our database will be bigger because every contact will have space for 3 phone numbers and 2 emails. Some of your contacts may have only 1 phone number and 1 email, which means that the other 3 fields are useless for that contact and will be left blank.
  2. What happens if you need a 4th number or a 3rd email field for a contact? Surely you can add a phone4 and email3 fields... but you're adding them to ALL the other contacts as well.

How can we solve this problem? Here's where the power of relational databases come in, we'll store the phone numbers and email addresses in separate tables and link them to the contacts table.

You have to think like this: one contact can have many phone numbers and also many emails. This means that the contact->phone_number relation is a one-to-many relation, the contact->email_address is also a one-to-many relation. Everytime you have a one-to-many relation you'll be creating separate tables to store information.

Let's modify our database design to reflect this:
Code:
------------     ------------     ------------
|contacts  |     |phones    |     |emails    |
------------     ------------     ------------
|contact_id|     |phone_id  |     |email_id  |
|name      |     |contact_id|     |contact_id|
|address   |     |number    |     |address   |
------------     ------------     ------------
The contacts table has a field called contact_id, this is a unique number that identifies a single contact. Similarly, the phones table has a phone_id field and the emails table have a email_id field, these fields are also unique numbers that identify each phone number and each email address.

Now if you look closer you'll notice that the phones (and emails) tables also have a contact_id field. This field is what links the tables so you know which contact is the owner of which phone(s) and email(s). The number stored in phones.contact_id is the same of contacts.contact_id. This is also the field we'll be using to join the tables together and retrieve all phone numbers and email addresses of a given contact.

Ok, let's say you wanna retrieve information about contact number 8, first you retrieve the main information from the contacts table:
Code:
SELECT name, address FROM contacts WHERE contact_id = 8;
Right, that was easy.. now let's retrieve all the phone numbers associated with contact number 8:
Code:
SELECT number FROM phones LEFT JOIN contacts ON phones.contact_id = contacts.contact_id WHERE contacts.contact_id = 8;
Same thing to get the emails:
Code:
SELECT address FROM emails LEFT JOIN contacts ON emails.contact_id = contacts.contact_id WHERE contacts.contact_id = 8;
See how I used the contact_id field in both tables to join them.

The concept of relational databases and how to design your tables in this form is a little confusing for starters. But if you practice a little and read some material on the subject you'll see that it's not all that complicated.

I hope this post helps you.

Last edited by DeMo : 02-01-2008 at 06:26 AM.
Send a message via ICQ to DeMo Send a message via MSN to DeMo Send a message via Skype™ to DeMo
DeMo is offline  
Reply With Quote
The Following 2 Users Say Thank You to DeMo For This Useful Post:
Aaron (02-01-2008), Haris (02-01-2008)
Old 02-01-2008, 02:40 AM   #5 (permalink)
The Frequenter
 
Join Date: Dec 2007
Location: In my basement
Posts: 368
Thanks: 44
Aaron is on a distinguished road
Default

DeMo, you deserve a medal for that post. It really helped me out, but when you got into joins I started getting confused. What books would you recommend?
Send a message via MSN to Aaron
Aaron is offline  
Reply With Quote
Old 02-01-2008, 07:36 AM   #6 (permalink)
The Contributor
 
DeMo's Avatar
 
Join Date: Jan 2008
Location: Brazil
Posts: 77
Thanks: 14
DeMo is on a distinguished road
Default

Wow, reading my post again I realized I made a huge mistake!!
Those JOINS are useless if we want to retrieve ONLY the phone numbers (or emails).

The correct query would be simply:
Code:
SELECT number FROM phones WHERE contact_id = 8;
Now let's get back on the JOIN.
As you can see, in my example I used three querys to get the information I wanted, the first one was used to get the main contact information, and the second and third were used to get the phones and emails. This isn't a very good practice because using a JOIN we can get all that information at once.

Joins are used when your data is scattered through multiple tables and you want to return them all at once. To be able to join tables you need to tell the database engine to look for similar data in the tables being joined, in our case this data is the contact_id field.

The basic syntax of a JOIN is like this:
Code:
SELECT
    <fields>
FROM
    <main_table>
LEFT JOIN
    <joined_table>
ON
    <main_table>.<join_field> = <joined_table>.<join_field>
WHERE
    <condition>;
If we want to retrieve our contact's name, address and phone numbers:
<fields> = name, address, number
Our main table is the contacts table, so:
<main_table> = contacts
The table being joined is the phones table:
<joined_table> = phones
The field we're using to make the join is the contact_id field:
<join_field> = contact_id
And since we want only the data from contact #8:
<condition> = contacts.contact_id = 8;

Putting everything together:
Code:
SELECT
    name, address, number
FROM
    contacts
LEFT JOIN
    phones
ON
    contacts.contact_id = phones.contact_id
WHERE
    contacts.contact_id = 8;
If we wanted to get the emails as well, all we need to do is attach another join after the first one, like this:
Code:
SELECT
    name, contacts.address, emails.address, number
FROM
    contacts
LEFT JOIN
    phones
ON
    contacts.contact_id = phones.contact_id
LEFT JOIN
    emails
ON
    contacts.contact_id = emails.contact_id
WHERE
    contacts.contact_id = 8;
Notice how I changed the <fields> part to contacts.address and emails.address. This is needed because these fields have the same name, since we want to return both we need to tell this explicitly to the database or else our query will fail. In the first example we weren't joining the emails table, so the only 'address' field that the database engine sees is the contacts.address field, so there's no need to explicitly tell the database that the address field we want is the one in the contacts table.

Another situation where a JOIN can make your life easier is when you have many-to-one relations. Suppose you're creating an application to catalog your DVDs, every DVD will have a title, duration and genre.
Code:
----------
|dvds    |
----------
|dvd_id  |
|title   |
|duration|
|genre   |
----------
If you store the genre as text every Action movie will have the string "Action" stored in that field. If tomorrow you decide that this genre should be renamed to "Action/Adventure" you'll need to update all the records in your database.

In this case we have a many-to-one relation, because one genre can be associated with many DVDs, but each DVD can only have one genre. In this case it's smarter to store the genre in a separate table that works like an index. Changing our design:
Code:
----------    ------------
|dvds    |    |genres    |
----------    ------------
|dvd_id  |    |genre_id  |
|title   |    |genre_name|
|duration|    ------------
|genre_id|
----------
The genres table works like an index:
  1. Action
  2. Comedy
  3. Musical

Notice how I changed the dvds table to have a genre_id field. This field will have the same value as the genre_id field in the genres table. This way, if you have an Action movie you only need to store the number 1 in the genre_id in the dvds table. If you decide to change the genre_name from "Action" to "Action/Adventure" you only need to do this in the genre table, all dvds that had genre_id = 1 have now virtually changed to "Action/Adventure".

Now let's suppose you want to produce a list of your DVDs showing their titles, duration and the genre. You can do this by retrieving all the dvds first, and then for each one of them you query the genre table to retrieve the genre. However, as we already know, this is NOT smart!! Both our tables have a genre_id field, so we can use it to JOIN the tables and retrieve all the information we want with just one query.

Here comes the JOIN again.
<fields> = title, duration, genre_name
<main_table> = dvds
<joined_table> = genres
<join_field> = genre_id
<condition> = none, because we are retrieving all records

Put everything in the query and we have:
Code:
SELECT
    title, duration, genre_name
FROM
    dvds
LEFT JOIN
    genres
ON
    dvds.genre_id = genres.genre_id;
And this concludes this tutorial-post.
I won't recommend any books to you 'cause I simply don't know anyone, I never really needed it. I learned the concept all by myself after some trial and error, reading other tutorials around the net and asking in forums like you're doing.

Maybe the more experienced guys can suggest a book for you, but I'm confident you can learn it all by yourself too, it just needs a little dedication.
Send a message via ICQ to DeMo Send a message via MSN to DeMo Send a message via Skype™ to DeMo
DeMo is offline  
Reply With Quote
The Following 2 Users Say Thank You to DeMo For This Useful Post:
Durux (04-10-2008)
Reply



Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


All times are GMT. The time now is 07:43 AM.

 
     

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.1.0