* Neil Watson 
> I'm thinking about an addressbook database.  I would like an opinion on
> my table layout (I still consider myself a mysql newbie):
> 
> table user
> uid
> username
> timestamp
> 
> table secret
> uid
> secret
> timestamp

You don't mention keys? Why do you want to split the user table? A more 'normal' 
approach would be something like this:

table user 
uid INT PRIMARY KEY
username varchar(30)
secret varchar(16)
created datetime
modified timestamp

You probably want an UNIQUE index on username, presuming this is what the user is 
going to use to log in to the database. The same index is used both to ensure you 
don't insert duplicate users and to do fast lookups on the users when they log in.

Note that I added an DATETIME column and gave a name to you TIMESTAMP column. Be aware 
of the difference between the data types DATETIME and TIMESTAMP: A TIMESTAMP column is 
changed automatically when any column in the row is changed, and it is set 
automatically to the current time when the row is created.

<URL: http://www.mysql.com/doc/en/DATETIME.html >

If you are going to use a web based front-end on your address book database, you may 
want a column in the user table for email address. A column for last_login could also 
be usefull. A 'hack' that could be usefull: add an pid to the user table. This pid 
points to a person-record for the user, i.e. with the users name, birthday, addresses 
and so on. The uid for that people record could be NULL if you don't want the user to 
be able to change his own address info (billing address?). Otherwise it is the uid for 
the user, and he can edit his own info in the same way as he edits any other person. 
Your application should probably prevent the user from deleting the person 
representing the user, even if you allow him to edit it. The user interface could also 
present the users personal info in a different way than other persons.

> table people
> pid
> uid
> firstname
> lastname
> birthday
> timestamp

The uid in the people table will prevent users from 'sharing' persons, but this may be 
just what you want. To be able to 'share' persons among users, you would have to 
remove uid from the person table, and use a separate table 'user_people' with the 
columns uid and pid.

The pid column should be an integer, and it should be the primary key of the people 
table. The uid column should be of same type as the user.uid column, and it should 
have an index, alone or as the first part of a combined index.

You should probably have an index on (uid,lastname) and (uid,firstname), but ... 

There is a weakness in this table design, the significance depends on the amount of 
persons you expect to handle for each user. The problem is that some persons have 
multiple first and/or last names. This prevents you from using ... WHERE ... LIKE 
'$criteria%' ... (Starting with the search criteria, ending with %). This is the 
syntax you need to use to utilize the index. If this is a 'normal' address book 
application, and you expect a few hundred persons per user, you should be okay, you 
can do scans through all people for the user with ... WHERE ... user.uid=people.uid 
AND people.firstname LIKE '%$firstname%' and people.lastname LIKE '%$lastname%' (note 
the leading %), and the index won't be used/needed.

> table address
> aid
> pid
> address
> city
> province
> country
> code
> address_type
> timestamp

The aid column should be an integer primary key, and the pid column should have an 
index. 

Again, if the amount of data is big, you should normalize this table further. You 
should have separate tables for country, city and province. With a small amount of 
data this may be overkill, the same issues as for the people table applies.

> table email
> eid
> pid
> alias
> string
> email
> timestamp

The ied column should be an integer primary key, and the pid column should be indexed.

I'm not sure what 'alias' and 'string' is supposed to store? Is it directly dependant 
on the email address? I guess 'alias' is to be used as a real name when sending email 
to this address? You could use 

CONCAT(people.firstname,' ',people.lastname) 

for that... or? I would expect the email table to contain only eid, pid, email and the 
timestamp column, if you need to know when the address was last modified or created.

I would have expected a similar table for phone numbers, optionally related to 
address: 

table phone
phid INT PRIMARY KEY
pid
aid 
phone varchar(12)

You would as usual need an index on pid, and one on aid. The aid column must accept 
NULL, which means a phone number is related to the person directly, not to the address 
(for mobile/cell phones). If you normalize more and have a separate country table, 
this table could also store the country code, and your application could for instance 
automatically add the right country code when the user lists foreign phone numbers. In 
that case you would probably also need a country code in the user table, unless all 
your users are guaranteed to be from the same country.

> Thoughts?

I think that was it. :)

HTH, 

-- 
Roger


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

Reply via email to