General rules for MySQL database tables, fields, indices and queries.
Engine is always MyISAM except in special case when required different. All databases must use UTF8 charset.
Database name must have the same name as project name. If the project name is "My Web Site" database should be created as:
CREATE DATABASE mywebsite DEFAULT CHARSET UTF8;
All tables must be UTF8 encoded. All tables in the same package must have prefix. Use 2 or 3 letters that describe the package to prefix database. If the project name is Real Deal Marketing, the most obvious prefix will be "rdm_";
CREATE TABLE rdm_affiliates;
All alterations for all tables should be saved in a (database_name).sql file. If database name is "realdealmarketing" filename should be realdealmarketing-1.0.0.sql
This section explains how to create database table fields and how to choose name for each field.
DROP TABLE IF EXISTS rdm_affiliates;
CREATE TABLE IF NOT EXISTS rdm_affiliates
(
aff_id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
aff_url VARCHAR(120) NOT NULL DEFAULT '',
aff_title VARCHAR(120) NOT NULL DEFAULT '',
aff_website CHAR(10) NOT NULL DEFAULT '',
aff_gender CHAR(8) NOT NULL DEFAULT '',
aff_landing_page VARCHAR(120) NOT NULL DEFAULT '',
aff_link VARCHAR(120) NOT NULL DEFAULT '',
aff_text TEXT,
PRIMARY KEY (aff_id),
INDEX (aff_website)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
All field names must be descriptive, avoid names like "unique", "sort" and reserved words.
All fields except AUTO_INCREAMENT, TEXT, DATE (and similar) must be defined as NOT NULL DEFAULT 'value'
Examples:
aff_title VARCHAR(120) NOT NULL DEFAULT ''
aff_gender ENUM('male','female') NOT NULL DEFAULT 'male'
user_id INT UNSIGNED NOT NULL DEFAULT 0
user_birthday DATE DEFAULT NULL
user_allow_newsletter TINYINT(1) UNSIGNED NOT NULL DEFAULT 0
art_text TEXT
All fields in WHERE and ORDER BY should be defined as INDEX. If you have query like this:
SELECT * FROM table1 WHERE a='something' ORDER BY b
Then fields a, b should be considered as indices
INDEX index_name (a,b)
If text field (CHAR, VARCHAR) is used as index for larger tables (> 5000 records) should be always defined as CHAR. For example, if you have fields like this:
aff_url VARCHAR(255) NOT NULL DEFAULT ''
...
INDEX afiliate_url (aff_url)
To improve performance, this table should be changed to something like this
aff_url CHAR(20) NOT NULL DEFAULT ''
...
INDEX afiliate_url (aff_url)
Reserved words should be uppercase to increase readability. Also try to separate long queries in multiple lines, while simple queries should stay in one line. Example:
SELECT a.field_name1, a.field_name2, COUNT(a.field3) AS cnt, b.*
FROM table1 AS a
LEFT JOIN table2 AS b ON (a.key_field = b.key_field)
RIGHT JOIN table3 AS c ON (a.key_field2 = c.key_field2)
WHERE a.field7 = 'something here' AND b.field9 = '45'
GROUP BY a.field_name1
ORDER BY a.field_name2 DESC, b.field8
HAVING cnt > 5
Always escape values in WHERE even when value is integer
PHP variables must be defined and escaped before query.
$q = "SELECT * FROM users WHERE email='"._escape($_POST['email'])."' ";
$email = _escape($_POST['email']);
if (empty($email))
{
return false;
}
$q = "SELECT * FROM users WHERE email='{$email}' ";
Try to avoid PHP My Admin for table creation because it has problems with default values. It's great product for browsing and simple database manipulation but it makes you lazy and you usually forget to keep history of table alteration and other changes.
Document created in december 2008. Version 1.0 beta