MySQL Cheat Sheet

A complete reference of MySQL syntax with 65 interactive examples. Copy code snippets or click “Try It” to run them directly in your browser.

Creating & Modifying Tables

CREATE TABLE

·

Create a new table with columns and constraints.

CREATE TABLE users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(255) NOT NULL,
  email VARCHAR(255) UNIQUE,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;

Tip: Use InnoDB engine for transaction support and foreign keys.

CREATE TABLE IF NOT EXISTS

·

Create a table only if it does not already exist.

CREATE TABLE IF NOT EXISTS logs (
  id INT AUTO_INCREMENT PRIMARY KEY,
  message TEXT,
  level VARCHAR(20) DEFAULT 'info'
);

ALTER TABLE ADD

·

Add a new column to an existing table.

ALTER TABLE users ADD COLUMN phone VARCHAR(20);

ALTER TABLE MODIFY

·

Change a column type or constraints.

ALTER TABLE users MODIFY COLUMN name VARCHAR(500) NOT NULL;

Tip: Use MODIFY to change type, CHANGE to also rename.

ALTER TABLE RENAME

·

Rename a table or column.

ALTER TABLE users CHANGE name full_name VARCHAR(255) NOT NULL;

DROP TABLE

·

Delete a table and all its data.

DROP TABLE IF EXISTS temp_data;

Tip: Use IF EXISTS to avoid errors when the table does not exist.

CREATE INDEX

·

Create an index to speed up queries.

CREATE INDEX idx_users_email ON users(email);

Tip: MySQL supports B-tree, Hash, Full-text, and Spatial indexes.

CREATE VIEW

·

Create a virtual table based on a SELECT query.

CREATE VIEW active_users AS
SELECT id, name, email FROM users
WHERE created_at > DATE_SUB(NOW(), INTERVAL 30 DAY);

CREATE DATABASE

·

Create a new database.

CREATE DATABASE IF NOT EXISTS myapp
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;

Tip: Use utf8mb4 for full Unicode support including emojis.

Adding & Changing Data

INSERT

·

Add new rows to a table.

INSERT INTO users (name, email)
VALUES ('Dave Wilson', 'dave@example.com');

SELECT * FROM users WHERE name = 'Dave Wilson';

INSERT Multiple Rows

·

Insert multiple rows in a single statement.

INSERT INTO products (name, category, price, stock) VALUES
  ('Headphones', 'Electronics', 149.99, 100),
  ('Webcam', 'Electronics', 89.99, 60);

SELECT * FROM products WHERE name IN ('Headphones', 'Webcam');

UPDATE

·

Modify existing rows in a table.

UPDATE orders SET status = 'shipped'
WHERE id = 3;

SELECT * FROM orders WHERE id = 3;

Tip: Always use WHERE to avoid updating all rows.

DELETE

·

Remove rows from a table.

DELETE FROM orders WHERE status = 'pending';

SELECT * FROM orders;

Tip: Always use WHERE unless you want to delete all rows.

REPLACE

·

Insert or replace a row if it exists.

REPLACE INTO users (id, name, email)
VALUES (1, 'Alice Updated', 'alice.new@example.com');

SELECT * FROM users WHERE id = 1;

Tip: REPLACE deletes then inserts; use ON DUPLICATE KEY for updates.

INSERT ON DUPLICATE KEY

·

Insert or update on primary key/unique conflict.

INSERT INTO users (id, name, email)
VALUES (2, 'Bob Updated', 'bob.new@example.com')
ON DUPLICATE KEY UPDATE
  name = VALUES(name),
  email = VALUES(email);

SELECT * FROM users WHERE id = 2;

Tip: VALUES() refers to the values that would have been inserted.

TRUNCATE

·

Quickly remove all rows from a table.

-- TRUNCATE is faster than DELETE for removing all rows
-- TRUNCATE TABLE logs;

Tip: TRUNCATE resets AUTO_INCREMENT; DELETE does not.

LOAD DATA

·

Bulk import data from a file.

-- Import from CSV
-- LOAD DATA INFILE '/tmp/users.csv'
-- INTO TABLE users
-- FIELDS TERMINATED BY ','
-- ENCLOSED BY '"'
-- LINES TERMINATED BY '\n'
-- IGNORE 1 ROWS;

Tip: Use LOCAL INFILE for client-side files.

Querying Data

SELECT

·

Retrieve data from one or more tables.

SELECT name, email FROM users;

SELECT *

·

Select all columns from a table.

SELECT * FROM products;

Tip: Avoid SELECT * in production; specify needed columns.

WHERE

·

Filter rows based on conditions.

SELECT * FROM orders WHERE price > 50 AND status = 'completed';

ORDER BY

·

Sort results by one or more columns.

SELECT * FROM products ORDER BY price DESC;

LIMIT & OFFSET

·

Limit the number of results and skip rows.

SELECT * FROM products ORDER BY price DESC LIMIT 3 OFFSET 1;

Tip: MySQL also supports LIMIT offset, count syntax.

GROUP BY

·

Group rows by column values for aggregation.

SELECT status, COUNT(*) as count, SUM(price) as total
FROM orders GROUP BY status;

HAVING

·

Filter groups after GROUP BY (like WHERE for groups).

SELECT user_id, COUNT(*) as order_count
FROM orders
GROUP BY user_id
HAVING COUNT(*) > 1;

DISTINCT

·

Return only unique values.

SELECT DISTINCT category FROM products;

INNER JOIN

·

Return rows where there is a match in both tables.

SELECT users.name, orders.product, orders.price
FROM orders
INNER JOIN users ON orders.user_id = users.id;

LEFT JOIN

·

Return all rows from left table, with matches from right.

SELECT users.name, orders.product
FROM users
LEFT JOIN orders ON users.id = orders.user_id;

Tip: Unmatched right table columns will be NULL.

Subquery

·

Use a query inside another query.

SELECT * FROM users
WHERE id IN (SELECT user_id FROM orders WHERE price > 100);

CTE (WITH clause)

·

Define a temporary named result set (MySQL 8.0+).

WITH high_value_orders AS (
  SELECT user_id, SUM(price) as total
  FROM orders
  GROUP BY user_id
  HAVING total > 100
)
SELECT users.name, high_value_orders.total
FROM high_value_orders
JOIN users ON users.id = high_value_orders.user_id;

Tip: CTEs require MySQL 8.0 or later.

UNION

·

Combine results from multiple SELECT statements.

SELECT name, 'user' as type FROM users
UNION ALL
SELECT name, 'product' as type FROM products;

Tip: UNION removes duplicates; UNION ALL keeps them.

Window Functions

·

Perform calculations across related rows (MySQL 8.0+).

SELECT name, price,
  ROW_NUMBER() OVER (ORDER BY price DESC) as row_rank,
  SUM(price) OVER () as total
FROM products;

Tip: Window functions require MySQL 8.0 or later.

Built-in Functions

COUNT

·

Count the number of rows.

SELECT COUNT(*) as total_orders FROM orders;

SUM & AVG

·

Calculate the sum or average of a column.

SELECT
  SUM(price) as total_revenue,
  AVG(price) as avg_order_value
FROM orders;

MIN & MAX

·

Find the minimum or maximum value.

SELECT MIN(price) as cheapest, MAX(price) as most_expensive
FROM products;

COALESCE / IFNULL

·

Return the first non-NULL value.

SELECT name, COALESCE(email, 'no email') as email
FROM users;

Tip: IFNULL is MySQL-specific; COALESCE is standard SQL.

NULLIF

·

Return NULL if two values are equal.

SELECT name, NULLIF(stock, 0) as stock_or_null
FROM products;

Tip: Useful for avoiding division by zero: x / NULLIF(y, 0)

CASE

·

Conditional logic in SQL (like if/else).

SELECT product, price,
  CASE
    WHEN price > 500 THEN 'expensive'
    WHEN price > 100 THEN 'moderate'
    ELSE 'affordable'
  END as price_tier
FROM orders;

IF

·

Simple conditional (MySQL-specific).

SELECT name, stock,
  IF(stock > 0, 'In Stock', 'Out of Stock') as availability
FROM products;

Tip: IF is simpler than CASE for two-way conditions.

String Functions

·

Manipulate text values.

SELECT
  UPPER(name) as uppercase,
  LENGTH(name) as name_length,
  SUBSTRING_INDEX(email, '@', 1) as username
FROM users;

Date Functions

·

Work with dates and times.

SELECT
  NOW() as current_time,
  CURDATE() as today,
  DATE_ADD(CURDATE(), INTERVAL 7 DAY) as next_week,
  YEAR(NOW()) as current_year;

JSON Functions

·

Extract and manipulate JSON data (MySQL 5.7+).

SELECT JSON_EXTRACT('{"name": "Alice", "age": 30}', '$.name') as name;

Tip: Use ->> for unquoted text extraction.

GROUP_CONCAT

·

Concatenate values from multiple rows.

SELECT user_id,
  GROUP_CONCAT(product SEPARATOR ', ') as products
FROM orders
GROUP BY user_id;

Tip: Default max length is 1024; increase with group_concat_max_len.

FIND_IN_SET

·

Find position of string in comma-separated list.

SELECT FIND_IN_SET('b', 'a,b,c,d') as position;

Tip: Returns 0 if not found, position (1-based) if found.

Data Rules & Constraints

PRIMARY KEY

·

Uniquely identify each row in a table.

CREATE TABLE employees (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(255) NOT NULL,
  department_id INT
);

Tip: AUTO_INCREMENT only works with integer primary keys.

FOREIGN KEY

·

Link to a row in another table.

CREATE TABLE orders (
  id INT AUTO_INCREMENT PRIMARY KEY,
  user_id INT,
  FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

Tip: Requires InnoDB engine. ON DELETE options: CASCADE, SET NULL, RESTRICT.

UNIQUE

·

Ensure all values in a column are different.

CREATE TABLE users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  email VARCHAR(255) UNIQUE,
  username VARCHAR(100) UNIQUE
);

NOT NULL

·

Prevent NULL values in a column.

CREATE TABLE products (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(255) NOT NULL,
  price DECIMAL(10,2) NOT NULL
);

DEFAULT

·

Set a default value when none is provided.

CREATE TABLE logs (
  id INT AUTO_INCREMENT PRIMARY KEY,
  message TEXT,
  level VARCHAR(20) DEFAULT 'info',
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Tip: Use ON UPDATE CURRENT_TIMESTAMP for auto-updating timestamps.

CHECK

·

Validate data against a condition (MySQL 8.0.16+).

CREATE TABLE products (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(255) NOT NULL,
  price DECIMAL(10,2) CHECK (price > 0),
  stock INT CHECK (stock >= 0)
);

Tip: CHECK constraints are enforced in MySQL 8.0.16+.

ENUM

·

Restrict column to predefined values.

CREATE TABLE orders (
  id INT AUTO_INCREMENT PRIMARY KEY,
  status ENUM('pending', 'processing', 'shipped', 'delivered') DEFAULT 'pending'
);

Tip: ENUM values are stored as integers internally.

Transactions

START TRANSACTION

·

Start a new transaction.

START TRANSACTION;

INSERT INTO users (name, email) VALUES ('Test', 'test@example.com');

-- Changes are not visible to other connections yet

Tip: MySQL defaults to autocommit=1; transactions disable it temporarily.

COMMIT

·

Save all changes made in the transaction.

START TRANSACTION;
INSERT INTO users (name, email) VALUES ('Test', 'test@example.com');
COMMIT;

SELECT * FROM users WHERE name = 'Test';

ROLLBACK

·

Undo all changes made in the transaction.

START TRANSACTION;
DELETE FROM users;
ROLLBACK;

-- Users table is unchanged
SELECT * FROM users;

SAVEPOINT

·

Create a point to rollback to within a transaction.

START TRANSACTION;
INSERT INTO users (name, email) VALUES ('A', 'a@test.com');
SAVEPOINT my_savepoint;
INSERT INTO users (name, email) VALUES ('B', 'b@test.com');
ROLLBACK TO SAVEPOINT my_savepoint;
COMMIT;

-- Only user 'A' was inserted
SELECT * FROM users WHERE email LIKE '%test.com';

LOCK TABLES

·

Explicitly lock tables.

-- Lock for reading (others can read but not write)
-- LOCK TABLES users READ;
-- SELECT * FROM users;
-- UNLOCK TABLES;

Tip: For row-level locking, use SELECT ... FOR UPDATE instead.

SELECT FOR UPDATE

·

Lock selected rows for update.

-- Lock specific rows
-- START TRANSACTION;
-- SELECT * FROM orders WHERE id = 1 FOR UPDATE;
-- UPDATE orders SET status = 'processing' WHERE id = 1;
-- COMMIT;

Tip: SKIP LOCKED (MySQL 8.0+) skips locked rows - great for queues.

Utilities & Advanced

SHOW Commands

·

Display database metadata.

SHOW TABLES;

DESCRIBE

·

Show table structure.

DESCRIBE users;

EXPLAIN

·

Show query execution plan.

EXPLAIN SELECT * FROM orders WHERE user_id = 1;

Tip: EXPLAIN ANALYZE (MySQL 8.0.18+) shows actual execution time.

OPTIMIZE TABLE

·

Reclaim space and defragment table.

-- Reclaim space after many DELETEs
-- OPTIMIZE TABLE orders;

Tip: For InnoDB, this rebuilds the table and updates statistics.

LIKE Pattern Matching

·

Match strings with wildcards.

SELECT * FROM users WHERE email LIKE '%@example.com';

Tip: LIKE is case-insensitive for non-binary strings.

REGEXP

·

Match patterns using regular expressions.

SELECT * FROM users WHERE email REGEXP '^[a-z]+@example\.com$';

Tip: REGEXP is case-insensitive by default; use BINARY for case-sensitive.

Full-Text Search

·

Search text columns efficiently.

-- Create fulltext index
-- ALTER TABLE products ADD FULLTEXT(name, category);

-- Natural language search
-- SELECT * FROM products
-- WHERE MATCH(name) AGAINST('laptop');

Tip: Supports natural language, boolean, and query expansion modes.

User Variables

·

Store values in session variables.

SET @total = 0;
SELECT @total := @total + price as running_total
FROM orders
ORDER BY id;

Tip: User variables persist for the session.

LAST_INSERT_ID

·

Get the last auto-increment value.

INSERT INTO users (name, email) VALUES ('New User', 'new@example.com');
SELECT LAST_INSERT_ID() as new_user_id;

Tip: Returns the ID for the current connection only.