Before PHP can save anything, the database and its tables must exist. You can create them in phpMyAdmin (click around) or by running SQL.
Create the database
CREATE DATABASE shop CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
utf8mb4 is the character set to use. It stores every character, including accents, Hindi letters and emoji. The older utf8 in MySQL is not full UTF-8, so avoid it.
Create a table
USE shop;
CREATE TABLE users (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(190) NOT NULL UNIQUE,
password_hash VARCHAR(255) NULL,
role VARCHAR(20) NOT NULL DEFAULT 'user',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Read each column definition: name, type, then rules.
| Part | Meaning |
|---|---|
INT UNSIGNED | A whole number from 0 up |
AUTO_INCREMENT | MySQL fills it with 1, 2, 3 … for each new row |
PRIMARY KEY | Unique identifier of the row |
VARCHAR(100) | Text up to 100 characters |
NOT NULL | The column must always have a value |
NULL | The column may be empty |
UNIQUE | No two rows may have the same value (two users cannot share an email) |
DEFAULT 'user' | Value used if you do not give one |
TIMESTAMP ... CURRENT_TIMESTAMP | Filled with the current time when the row is created |
ENGINE=InnoDB | The storage engine that supports transactions and relations |
Common data types
| Type | Use for |
|---|---|
INT, BIGINT | Whole numbers |
DECIMAL(10,2) | Money. Exact decimals (not FLOAT, see Floating-Point Pitfalls) |
VARCHAR(n) | Short text (names, emails, titles) |
TEXT | Long text (article body) |
TINYINT(1) or BOOLEAN | Yes or no |
DATE, DATETIME, TIMESTAMP | Dates and times |
ENUM('a','b') | One value from a short fixed list |
JSON | JSON documents |
A table for products
CREATE TABLE products (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(150) NOT NULL,
price DECIMAL(10,2) NOT NULL,
stock INT NOT NULL DEFAULT 0,
category VARCHAR(50) NOT NULL DEFAULT 'general'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Relations: a foreign key
A post belongs to a user, so posts.user_id points to users.id.
CREATE TABLE posts (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_id INT UNSIGNED NOT NULL,
title VARCHAR(200) NOT NULL,
body TEXT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
The foreign key stops you from creating a post for a user that does not exist. ON DELETE CASCADE deletes a user’s posts when the user is deleted.
Add some data
INSERT INTO users (name, email) VALUES
('Ana', 'ana@example.com'),
('Ben', 'ben@example.com');
Use phpMyAdmin
- Open phpMyAdmin (for example
http://localhost/phpmyadmin). - Click New, type a database name and choose
utf8mb4_unicode_ci. - Create a table, add columns, choose types, tick A_I (AUTO_INCREMENT) for the id and make it the primary key.
- Use the SQL tab to paste the commands above.
Design tips
- Every table gets an
idprimary key. - Use singular or plural names consistently (
users,products). - Store one fact in one place. Do not copy a user’s name into every post.
- Index columns that you search often (
email,category). Primary and unique keys are already indexed. - Never store plain passwords. The column holds a hash (see Password Hashing).
Keep the SQL in a file
schema.sql in your project, so you and your teammates can recreate the database at any time.