- Basic MySQL Commands
- Connecting to MySQL Server
- Authentication and Users
- Database Management
- Table Management
- Column Data Types
- Inserting Data
- Selecting Data
- Filtering Data
- Sorting Results
- Limiting Results
- Updating Data
- Deleting Data
- Joins
- Grouping and Aggregating
- Subqueries
- Views
- Indexes
- Transactions
- Stored Procedures and Functions
- Triggers
- Backup and Restore
- Importing and Exporting Data
- User Privileges and Permissions
- Managing Connections and Sessions
- Configuration Files and Server Settings
- Performance Optimization
- Error Handling
- Working with Dates and Times
- String Functions
- Numeric and Mathematical Functions
- JSON Functions
- Administrative Commands
- Replication Basics
- Security Best Practices
- Common Server Commands
- Version Differences
Basic MySQL Commands
Command | Description | Example |
---|---|---|
SELECT | Retrieve data from a database | SELECT column1, column2 FROM table_name; |
INSERT | Add new data to a table | INSERT INTO table_name (column1, column2) VALUES (value1, value2); |
UPDATE | Modify existing data in a table | UPDATE table_name SET column1 = value1 WHERE condition; |
DELETE | Remove data from a table | DELETE FROM table_name WHERE condition; |
CREATE | Create new databases or tables | CREATE TABLE table_name (column1 datatype, column2 datatype); |
ALTER | Modify database objects | ALTER TABLE table_name ADD column_name datatype; |
DROP | Delete databases or tables | DROP TABLE table_name; |
SHOW | Display information about databases, tables, etc. | SHOW DATABASES; SHOW TABLES; |
USE | Select a database to work with | USE database_name; |
DESCRIBE or DESC | Show structure of a table | DESCRIBE table_name; DESC table_name; |
Connecting to MySQL Server
Command | Description | Example |
---|---|---|
mysql | Basic connection to local MySQL server | mysql -u username -p |
mysql with password | Connect with password (not recommended for production) | mysql -u username -ppassword |
mysql with specific host | Connect to MySQL on a specific host | mysql -h hostname -u username -p |
mysql with port | Connect using a non-default port | mysql -h hostname -P 3307 -u username -p |
mysql with database | Connect and select a specific database | mysql -u username -p database_name |
mysql with socket | Connect using a specific socket file | mysql -u username -p --socket=/path/to/mysql.sock |
mysqladmin | Perform administrative operations | mysqladmin -u root -p version |
Connection via config file | Connect using settings in my.cnf/my.ini | mysql --defaults-file=/path/to/my.cnf |
Connection timeout | Set connection timeout in seconds | mysql -u username -p --connect-timeout=10 |
SSL connection | Connect using SSL for security | mysql -u username -p --ssl-ca=/path/to/ca.pem |
Authentication and Users
Command | Description | Example |
---|---|---|
CREATE USER | Create a new MySQL user | CREATE USER 'username'@'localhost' IDENTIFIED BY 'password'; |
DROP USER | Delete a MySQL user | DROP USER 'username'@'localhost'; |
SET PASSWORD | Change a user’s password | SET PASSWORD FOR 'username'@'localhost' = PASSWORD('new_password'); |
ALTER USER | Modify user properties (MySQL 5.7+) | ALTER USER 'username'@'localhost' IDENTIFIED BY 'new_password'; |
RENAME USER | Rename a user | RENAME USER 'old_username'@'localhost' TO 'new_username'@'localhost'; |
GRANT | Grant privileges to a user | GRANT SELECT, INSERT ON database_name.* TO 'username'@'localhost'; |
REVOKE | Remove privileges from a user | REVOKE INSERT ON database_name.* FROM 'username'@'localhost'; |
SHOW GRANTS | Show privileges for a user | SHOW GRANTS FOR 'username'@'localhost'; |
FLUSH PRIVILEGES | Reload the privilege tables | FLUSH PRIVILEGES; |
Current user info | Display the current user and host | SELECT USER(), CURRENT_USER(); |
Database Management
Command | Description | Example |
---|---|---|
CREATE DATABASE | Create a new database | CREATE DATABASE database_name; |
CREATE DATABASE with character set | Create a database with specific character set | CREATE DATABASE database_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; |
DROP DATABASE | Delete a database | DROP DATABASE database_name; |
SHOW DATABASES | List all databases on the server | SHOW DATABASES; |
USE | Switch to a specific database | USE database_name; |
SHOW CREATE DATABASE | Show the CREATE statement for a database | SHOW CREATE DATABASE database_name; |
ALTER DATABASE | Modify database properties | ALTER DATABASE database_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; |
Check size of database | Get the total size of a database | SELECT table_schema AS "Database", ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS "Size (MB)" FROM information_schema.TABLES WHERE table_schema = "database_name" GROUP BY table_schema; |
Check database existence | Check if a database exists before creating | CREATE DATABASE IF NOT EXISTS database_name; |
Database information | Get information about databases | SELECT * FROM information_schema.SCHEMATA; |
Table Management
Command | Description | Example |
---|---|---|
CREATE TABLE | Create a new table | CREATE TABLE table_name ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100) NOT NULL, email VARCHAR(100) UNIQUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); |
CREATE TABLE like another | Create a table with the same structure as another | CREATE TABLE new_table LIKE existing_table; |
DROP TABLE | Delete a table | DROP TABLE table_name; |
TRUNCATE TABLE | Delete all data from a table, but keep structure | TRUNCATE TABLE table_name; |
ALTER TABLE add column | Add a new column to a table | ALTER TABLE table_name ADD COLUMN column_name VARCHAR(50); |
ALTER TABLE modify column | Change a column’s data type | ALTER TABLE table_name MODIFY COLUMN column_name VARCHAR(100); |
ALTER TABLE drop column | Remove a column from a table | ALTER TABLE table_name DROP COLUMN column_name; |
ALTER TABLE rename column | Rename a column | ALTER TABLE table_name CHANGE COLUMN old_name new_name VARCHAR(100); |
ALTER TABLE add index | Add an index to a table | ALTER TABLE table_name ADD INDEX idx_name (column_name); |
ALTER TABLE add foreign key | Add a foreign key constraint | ALTER TABLE table_name ADD CONSTRAINT fk_name FOREIGN KEY (column_name) REFERENCES ref_table(ref_column); |
RENAME TABLE | Rename a table | RENAME TABLE old_name TO new_name; |
SHOW TABLES | List all tables in the current database | SHOW TABLES; |
DESCRIBE or DESC | Show the structure of a table | DESCRIBE table_name; DESC table_name; |
SHOW CREATE TABLE | Show the CREATE statement for a table | SHOW CREATE TABLE table_name; |
Table size | Get the size of a table | SELECT table_name AS "Table", round(((data_length + index_length) / 1024 / 1024), 2) AS "Size (MB)" FROM information_schema.TABLES WHERE table_schema = "database_name" AND table_name = "table_name"; |
Column Data Types
Data Type | Description | Example |
---|---|---|
Numeric Types | ||
INT | Integer (-2,147,483,648 to 2,147,483,647) | age INT |
TINYINT | Very small integer (-128 to 127) | is_active TINYINT(1) |
SMALLINT | Small integer (-32,768 to 32,767) | quantity SMALLINT |
MEDIUMINT | Medium-sized integer (-8,388,608 to 8,388,607) | population MEDIUMINT |
BIGINT | Large integer (-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807) | views BIGINT |
DECIMAL | Fixed-point number (for currency or precise values) | price DECIMAL(10,2) |
FLOAT | Single-precision floating-point number | temperature FLOAT |
DOUBLE | Double-precision floating-point number | scientific_value DOUBLE |
String Types | ||
CHAR | Fixed-length string (0-255 chars) | state_code CHAR(2) |
VARCHAR | Variable-length string (0-65,535 chars) | username VARCHAR(50) |
TINYTEXT | String up to 255 characters | short_note TINYTEXT |
TEXT | String up to 65,535 characters | description TEXT |
MEDIUMTEXT | String up to 16,777,215 characters | content MEDIUMTEXT |
LONGTEXT | String up to 4,294,967,295 characters | full_document LONGTEXT |
ENUM | String with a value chosen from a list | status ENUM('active', 'inactive', 'pending') |
SET | String that can have 0 or more values from a list | permissions SET('read', 'write', 'execute') |
Date and Time Types | ||
DATE | Date (YYYY-MM-DD) | birth_date DATE |
TIME | Time (HH:MM:SS) | appointment_time TIME |
DATETIME | Date and time (YYYY-MM-DD HH:MM:SS) | registered_at DATETIME |
TIMESTAMP | Timestamp, auto-updated on change, UTC-based | last_update TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
YEAR | Year in 4-digit format | graduation_year YEAR |
Binary Types | ||
BINARY | Fixed-length binary string | file_signature BINARY(16) |
VARBINARY | Variable-length binary string | encryption_key VARBINARY(128) |
TINYBLOB | Binary Large Object up to 255 bytes | small_image TINYBLOB |
BLOB | Binary Large Object up to 65,535 bytes | medium_image BLOB |
MEDIUMBLOB | Binary Large Object up to 16,777,215 bytes | large_image MEDIUMBLOB |
LONGBLOB | Binary Large Object up to 4,294,967,295 bytes | file_content LONGBLOB |
Spatial Types | ||
GEOMETRY | Any type of geometry | shape GEOMETRY |
POINT | A point (X, Y) | location POINT |
LINESTRING | A curve with linear interpolation | route LINESTRING |
POLYGON | A polygon | area POLYGON |
JSON Type (MySQL 5.7+) | ||
JSON | Native JSON storage and validation | settings JSON |
Inserting Data
Command | Description | Example |
---|---|---|
INSERT basic syntax | Insert a single row | INSERT INTO table_name (column1, column2) VALUES (value1, value2); |
INSERT multiple rows | Insert multiple rows at once | INSERT INTO table_name (column1, column2) VALUES (value1, value2), (value3, value4), (value5, value6); |
INSERT all columns | Insert when providing values for all columns | INSERT INTO table_name VALUES (value1, value2, value3); |
INSERT IGNORE | Insert row, ignore errors (e.g., duplicates) | INSERT IGNORE INTO table_name (column1, column2) VALUES (value1, value2); |
INSERT ... ON DUPLICATE KEY UPDATE | Insert or update if duplicate key | INSERT INTO table_name (id, column1, column2) VALUES (1, value1, value2) ON DUPLICATE KEY UPDATE column1 = value1, column2 = value2; |
INSERT ... SELECT | Insert data from another table | INSERT INTO target_table (column1, column2) SELECT column1, column2 FROM source_table WHERE condition; |
REPLACE | Insert a row, or replace if exists | REPLACE INTO table_name (column1, column2) VALUES (value1, value2); |
Using expressions | Insert with expressions or functions | INSERT INTO table_name (name, created_at) VALUES ('Example', NOW()); |
Default values | Insert using default values | INSERT INTO table_name (id, name, created_at) VALUES (NULL, 'Example', DEFAULT); |
Batch insert | Insert multiple rows efficiently | INSERT INTO table_name (column1, column2) VALUES (value1, value2), (value3, value4), ... (valueN-1, valueN); |
Selecting Data
Command | Description | Example |
---|---|---|
SELECT basic syntax | Select specific columns from a table | SELECT column1, column2 FROM table_name; |
SELECT * | Select all columns | SELECT * FROM table_name; |
SELECT DISTINCT | Select unique values | SELECT DISTINCT column1 FROM table_name; |
SELECT with alias | Rename columns in results | SELECT column1 AS alias1, column2 AS alias2 FROM table_name; |
SELECT with table alias | Use table aliases for shorter queries | SELECT t.column1, t.column2 FROM table_name AS t; |
SELECT with calculations | Perform calculations in select queries | SELECT price, quantity, price * quantity AS total FROM orders; |
SELECT with functions | Use functions in selects | SELECT name, UPPER(name) AS uppercase_name, LENGTH(name) AS name_length FROM customers; |
SELECT with CASE | Conditional logic in selects | SELECT name, age, CASE WHEN age < 18 THEN 'Minor' WHEN age >= 18 AND age < 65 THEN 'Adult' ELSE 'Senior' END AS age_category FROM users; |
SELECT with IF | Simple conditional expressions | SELECT name, IF(active = 1, 'Active', 'Inactive') AS status FROM users; |
SELECT with COALESCE | Return first non-NULL value | SELECT name, COALESCE(phone, email, 'No Contact') AS contact FROM customers; |
Filtering Data
Command | Description | Example |
---|---|---|
WHERE clause | Basic filter condition | SELECT * FROM users WHERE age > 18; |
WHERE with multiple conditions | Combine conditions with AND/OR | SELECT * FROM products WHERE category = 'Electronics' AND price < 1000; |
WHERE with IN | Match against a list of values | SELECT * FROM products WHERE category IN ('Electronics', 'Computers', 'Accessories'); |
WHERE with NOT IN | Exclude a list of values | SELECT * FROM products WHERE category NOT IN ('Clothing', 'Furniture'); |
WHERE with BETWEEN | Match values in a range | SELECT * FROM products WHERE price BETWEEN 100 AND 500; |
WHERE with LIKE | Pattern matching with wildcards | SELECT * FROM users WHERE name LIKE 'J%'; -- Names starting with J -- % matches any number of characters -- _ matches exactly one character |
WHERE with NOT LIKE | Exclude pattern matches | SELECT * FROM users WHERE email NOT LIKE '%@gmail.com'; |
WHERE with REGEXP | Regular expression matching | SELECT * FROM users WHERE name REGEXP '^[AEI]'; -- Names starting with A, E, or I |
WHERE with IS NULL | Find records with NULL values | SELECT * FROM users WHERE phone IS NULL; |
WHERE with IS NOT NULL | Find records with non-NULL values | SELECT * FROM users WHERE phone IS NOT NULL; |
WHERE with subquery | Filter based on subquery results | SELECT * FROM products WHERE category_id IN ( SELECT id FROM categories WHERE active = 1 ); |
WHERE with EXISTS | Check existence of related records | SELECT * FROM customers WHERE EXISTS ( SELECT 1 FROM orders WHERE orders.customer_id = customers.id ); |
Sorting Results
Command | Description | Example |
---|---|---|
ORDER BY single column | Sort by one column (ascending by default) | SELECT * FROM users ORDER BY last_name; |
ORDER BY with ASC | Sort in ascending order (default) | SELECT * FROM products ORDER BY price ASC; |
ORDER BY with DESC | Sort in descending order | SELECT * FROM products ORDER BY price DESC; |
ORDER BY multiple columns | Sort by multiple columns | SELECT * FROM users ORDER BY last_name ASC, first_name ASC; |
ORDER BY mixed directions | Sort different columns in different directions | SELECT * FROM products ORDER BY category ASC, price DESC; |
ORDER BY with expressions | Sort by calculated values | SELECT *, price * quantity AS total FROM order_items ORDER BY total DESC; |
ORDER BY with FIELD | Custom sort order | SELECT * FROM products ORDER BY FIELD(status, 'Featured', 'Active', 'Inactive'); |
ORDER BY with CASE | Conditional sorting | SELECT * FROM orders ORDER BY CASE WHEN status = 'Processing' THEN 1 WHEN status = 'Shipped' THEN 2 ELSE 3 END; |
ORDER BY with NULL handling | Control how NULL values are sorted | -- NULL values first SELECT * FROM users ORDER BY phone IS NOT NULL, phone ASC; -- NULL values last SELECT * FROM users ORDER BY phone IS NULL, phone ASC; |
ORDER BY column position | Sort by column position (avoid in production) | SELECT name, price, category FROM products ORDER BY 2 DESC; -- Sort by price (the 2nd column) |
Limiting Results
Command | Description | Example |
---|---|---|
LIMIT basic | Limit the number of rows returned | SELECT * FROM products LIMIT 10; |
LIMIT with OFFSET | Skip some rows and return the rest | SELECT * FROM products LIMIT 10 OFFSET 20; -- Skip 20 rows, return next 10 |
LIMIT shorthand | Alternative syntax with offset first | SELECT * FROM products LIMIT 20, 10; -- Skip 20 rows, return next 10 |
LIMIT for pagination | Get a specific page of results | -- For page 3 with 10 items per page SELECT * FROM products LIMIT 10 OFFSET 20; -- (page - 1) * items_per_page |
LIMIT with ORDER BY | Get top N rows by a criteria | -- Top 5 most expensive products SELECT * FROM products ORDER BY price DESC LIMIT 5; |
LIMIT in subquery | Use limits in subqueries | SELECT * FROM orders WHERE customer_id IN ( SELECT id FROM customers ORDER BY total_spend DESC LIMIT 10 ); |
LIMIT random row | Get a random row | SELECT * FROM products ORDER BY RAND() LIMIT 1; |
LIMIT with aggregations | Find top values after grouping | -- Top 3 categories by total sales SELECT category, SUM(price * quantity) AS total_sales FROM order_items JOIN products ON order_items.product_id = products.id GROUP BY category ORDER BY total_sales DESC LIMIT 3; |
LIMIT with variables | Using variables for dynamic limits | -- Using prepared statements PREPARE stmt FROM 'SELECT * FROM products LIMIT ?'; SET @limit = 5; EXECUTE stmt USING @limit; DEALLOCATE PREPARE stmt; |
No LIMIT clause | Return all matching rows (use with caution) | SELECT * FROM products; -- No limit, returns all rows |
Updating Data
Command | Description | Example |
---|---|---|
UPDATE basic syntax | Update one or more columns in one or more rows | UPDATE table_name SET column1 = value1, column2 = value2 WHERE condition; |
UPDATE all rows | Update all rows (be careful!) | -- Update all rows (use with caution) UPDATE products SET in_stock = 0; |
UPDATE with expressions | Update using expressions or calculations | UPDATE products SET price = price * 1.1 -- Increase price by 10% WHERE category = 'Electronics'; |
UPDATE with functions | Update using functions | UPDATE users SET last_login = NOW(), login_count = login_count + 1 WHERE id = 123; |
UPDATE with CASE | Conditional updates | UPDATE orders SET status = CASE WHEN payment_received = 1 AND shipped = 0 THEN 'Paid' WHEN payment_received = 1 AND shipped = 1 THEN 'Completed' ELSE 'Pending' END; |
UPDATE with LIMIT | Limit the number of rows to update | UPDATE users SET status = 'inactive' WHERE last_login < DATE_SUB(NOW(), INTERVAL 1 YEAR) LIMIT 100; |
UPDATE with ORDER BY | Update rows in a specific order | UPDATE products SET featured = 1 WHERE category = 'Electronics' ORDER BY price DESC LIMIT 5; |
UPDATE with subquery | Update based on data from other tables | UPDATE employees SET salary = salary * 1.1 WHERE department_id IN ( SELECT id FROM departments WHERE performance_rating > 8 ); |
UPDATE with JOIN | Update data based on joined tables | UPDATE orders o JOIN customers c ON o.customer_id = c.id SET o.discount = 0.1 WHERE c.loyalty_points > 1000; |
UPDATE IGNORE | Continue update even if errors occur | UPDATE IGNORE users SET email = LOWER(email), username = LOWER(username); |
Deleting Data
Command | Description | Example |
---|---|---|
DELETE basic syntax | Delete rows from a table | DELETE FROM table_name WHERE condition; |
DELETE all rows | Delete all rows (be very careful!) | -- Delete all rows (use with extreme caution) DELETE FROM temporary_logs; |
DELETE with LIMIT | Limit the number of rows to delete | DELETE FROM logs WHERE created_at < DATE_SUB(NOW(), INTERVAL 1 YEAR) LIMIT 1000; |
DELETE with ORDER BY | Delete rows in a specific order | DELETE FROM logs WHERE type = 'error' ORDER BY created_at LIMIT 100; |
DELETE with subquery | Delete based on a subquery | DELETE FROM cart_items WHERE user_id IN ( SELECT id FROM users WHERE last_activity < DATE_SUB(NOW(), INTERVAL 30 DAY) ); |
DELETE with multiple tables | Delete from multiple tables at once | DELETE c, o FROM customers c JOIN orders o ON c.id = o.customer_id WHERE c.active = 0; |
TRUNCATE TABLE | Delete all rows (faster than DELETE, resets AUTO_INCREMENT) | TRUNCATE TABLE logs; |
DELETE vs TRUNCATE | Differences between DELETE and TRUNCATE | -- DELETE: one by one, can be rolled back, preserves AUTO_INCREMENT DELETE FROM table_name; -- TRUNCATE: drops and recreates table, faster, resets AUTO_INCREMENT TRUNCATE TABLE table_name; |
Soft delete | Mark records as deleted instead of actual deletion | -- Instead of deleting the records UPDATE users SET deleted_at = NOW(), active = 0 WHERE id = 123; |
DELETE IGNORE | Continue delete operation even if errors occur | DELETE IGNORE FROM products WHERE category_id = 5; |
Joins
Command | Description | Example |
---|---|---|
INNER JOIN | Return rows when there is a match in both tables | SELECT o.id, c.name FROM orders o INNER JOIN customers c ON o.customer_id = c.id; |
LEFT JOIN | Return all rows from left table and matched rows from right table | SELECT c.name, o.id FROM customers c LEFT JOIN orders o ON c.id = o.customer_id; |
RIGHT JOIN | Return all rows from right table and matched rows from left table | SELECT o.id, p.name FROM orders o RIGHT JOIN products p ON o.product_id = p.id; |
FULL OUTER JOIN (emulated) | Return rows when there is a match in either table (MySQL doesn't directly support FULL JOIN) | -- Emulating FULL JOIN in MySQL SELECT c.name, o.id FROM customers c LEFT JOIN orders o ON c.id = o.customer_id UNION SELECT c.name, o.id FROM customers c RIGHT JOIN orders o ON c.id = o.customer_id WHERE c.id IS NULL; |
CROSS JOIN | Return the Cartesian product (all combinations of rows) | SELECT c.name, p.name FROM customers c CROSS JOIN products p; |
Self Join | Join a table to itself | SELECT e1.name AS employee, e2.name AS manager FROM employees e1 JOIN employees e2 ON e1.manager_id = e2.id; |
Multiple Joins | Join more than two tables | SELECT o.id, c.name, p.name, p.price FROM orders o JOIN customers c ON o.customer_id = c.id JOIN order_items oi ON o.id = oi.order_id JOIN products p ON oi.product_id = p.id; |
Join with conditions | Add WHERE clauses to filter joined data | SELECT o.id, c.name FROM orders o JOIN customers c ON o.customer_id = c.id WHERE o.status = 'shipped' AND c.country = 'USA'; |
Join with USING | Join tables with identically named columns | SELECT o.id, c.name FROM orders o JOIN customers c USING (customer_id); |
Join with NATURAL JOIN | Join based on all columns with same name (use with caution) | SELECT o.id, c.name FROM orders o NATURAL JOIN customers c; |
Grouping and Aggregating
Command | Description | Example |
---|---|---|
GROUP BY basic | Group rows that have the same values | SELECT category, COUNT(*) AS product_count FROM products GROUP BY category; |
COUNT() | Count the number of rows or non-NULL values | -- Count all rows SELECT COUNT(*) FROM orders; -- Count non-NULL values in a column SELECT COUNT(phone) FROM customers; |
SUM() | Calculate the sum of values | SELECT category, SUM(price) AS total_value FROM products GROUP BY category; |
AVG() | Calculate the average of values | SELECT category, AVG(price) AS average_price FROM products GROUP BY category; |
MIN() | Find the minimum value | SELECT category, MIN(price) AS lowest_price FROM products GROUP BY category; |
MAX() | Find the maximum value | SELECT category, MAX(price) AS highest_price FROM products GROUP BY category; |
GROUP_CONCAT() | Concatenate values from grouped rows | SELECT category, GROUP_CONCAT(name SEPARATOR ', ') AS products FROM products GROUP BY category; |
HAVING clause | Filter groups based on aggregate functions | SELECT category, COUNT(*) AS product_count FROM products GROUP BY category HAVING product_count > 5; |
WITH ROLLUP | Include summary rows | SELECT category, subcategory, SUM(price) AS total FROM products GROUP BY category, subcategory WITH ROLLUP; |
Multiple aggregations | Use multiple aggregate functions together | SELECT category, COUNT(*) AS count, MIN(price) AS min_price, MAX(price) AS max_price, AVG(price) AS avg_price, SUM(price) AS total_value FROM products GROUP BY category; |
Group by multiple columns | Group by more than one column | SELECT category, manufacturer, COUNT(*) AS product_count FROM products GROUP BY category, manufacturer ORDER BY category, product_count DESC; |
Group by with join | Group results from joined tables | SELECT c.country, COUNT(o.id) AS order_count FROM customers c JOIN orders o ON c.id = o.customer_id GROUP BY c.country ORDER BY order_count DESC; |
Subqueries
Command | Description | Example |
---|---|---|
Subquery in WHERE | Use a subquery in WHERE clause | SELECT name FROM products WHERE category_id IN ( SELECT id FROM categories WHERE parent_id = 5 ); |
Subquery with comparison | Compare to a single value from subquery | SELECT name, price FROM products WHERE price > ( SELECT AVG(price) FROM products ); |
Subquery with IN | Check if a value is in the result set | SELECT * FROM customers WHERE id IN ( SELECT DISTINCT customer_id FROM orders WHERE total > 1000 ); |
Subquery with NOT IN | Check if a value is not in the result set | SELECT * FROM products WHERE id NOT IN ( SELECT product_id FROM order_items ); |
Subquery with EXISTS | Check if the subquery returns any rows | SELECT * FROM customers c WHERE EXISTS ( SELECT 1 FROM orders o WHERE o.customer_id = c.id AND o.created_at > DATE_SUB(NOW(), INTERVAL 30 DAY) ); |
Subquery with NOT EXISTS | Check if the subquery returns no rows | SELECT * FROM products p WHERE NOT EXISTS ( SELECT 1 FROM order_items oi WHERE oi.product_id = p.id ); |
Subquery in SELECT | Use a subquery in SELECT statement | SELECT name, price, (SELECT AVG(price) FROM products) AS avg_price, price - (SELECT AVG(price) FROM products) AS diff_from_avg FROM products; |
Correlated subquery | Subquery that references the outer query | SELECT p1.name, p1.price FROM products p1 WHERE p1.price > ( SELECT AVG(p2.price) FROM products p2 WHERE p2.category_id = p1.category_id ); |
Subquery in FROM | Use a subquery as a derived table | SELECT category, avg_price FROM ( SELECT category, AVG(price) AS avg_price FROM products GROUP BY category ) AS category_stats WHERE avg_price > 100; |
Subquery with ALL | Compare with all values returned by subquery | SELECT name, price FROM products WHERE price > ALL ( SELECT price FROM products WHERE category_id = 3 ); |
Subquery with ANY | Compare with any value returned by subquery | SELECT name, price FROM products WHERE price > ANY ( SELECT price FROM products WHERE category_id = 3 ); |
Scalar subquery | Subquery that returns exactly one value | SELECT name, price, (SELECT MAX(price) FROM products) AS max_price, price / (SELECT MAX(price) FROM products) * 100 AS percentage_of_max FROM products; |
Views
Command | Description | Example |
---|---|---|
CREATE VIEW | Create a virtual table based on a SELECT query | CREATE VIEW product_details AS SELECT p.id, p.name, p.price, c.name AS category FROM products p JOIN categories c ON p.category_id = c.id; |
CREATE OR REPLACE VIEW | Create a view or replace it if it exists | CREATE OR REPLACE VIEW high_value_customers AS SELECT id, name, email, total_orders FROM customers WHERE total_orders > 10; |
DROP VIEW | Delete a view | DROP VIEW product_details; |
DROP VIEW IF EXISTS | Delete a view if it exists | DROP VIEW IF EXISTS product_details; |
SHOW CREATE VIEW | Show the CREATE VIEW statement | SHOW CREATE VIEW product_details; |
ALTER VIEW | Modify a view definition | ALTER VIEW product_details AS SELECT p.id, p.name, p.price, p.description, c.name AS category FROM products p JOIN categories c ON p.category_id = c.id; |
Selecting from a view | Query a view just like a regular table | SELECT * FROM product_details WHERE price > 100; |
View with WITH CHECK OPTION | Prevents updates that would make rows not visible through the view | CREATE VIEW active_products AS SELECT id, name, price, status FROM products WHERE status = 'active' WITH CHECK OPTION; |
Updatable view | View that allows UPDATE, INSERT, DELETE operations | CREATE VIEW basic_product_info AS SELECT id, name, price, category_id FROM products; |
View with join (read-only) | Views with joins are generally read-only | CREATE VIEW order_summary AS SELECT o.id AS order_id, c.name AS customer_name, o.total AS order_total, o.created_at AS order_date FROM orders o JOIN customers c ON o.customer_id = c.id; |
View with aggregation | Create a view with aggregate functions | CREATE VIEW category_stats AS SELECT category_id, COUNT(*) AS product_count, AVG(price) AS avg_price, MIN(price) AS min_price, MAX(price) AS max_price FROM products GROUP BY category_id; |
Using views for security | Limit access to specific columns or rows | CREATE VIEW public_customer_info AS SELECT id, name, city, country FROM customers; -- Then grant access to this view instead of the base table GRANT SELECT ON public_customer_info TO 'app_user'@'localhost'; |
Indexes
Command | Description | Example |
---|---|---|
CREATE INDEX | Create an index on a table column | CREATE INDEX idx_last_name ON users(last_name); |
CREATE UNIQUE INDEX | Create an index that enforces uniqueness | CREATE UNIQUE INDEX idx_email ON users(email); |
Composite index | Create an index on multiple columns | CREATE INDEX idx_name_email ON users(last_name, first_name, email); |
Primary key index | Create a primary key (automatically indexed) | CREATE TABLE users ( id INT PRIMARY KEY, name VARCHAR(100) ); |
Foreign key index | Create a foreign key (best to index it) | CREATE TABLE orders ( id INT PRIMARY KEY, user_id INT, total DECIMAL(10,2), INDEX idx_user_id (user_id), FOREIGN KEY (user_id) REFERENCES users(id) ); |
SHOW INDEXES | List all indexes on a table | SHOW INDEXES FROM table_name; |
DROP INDEX | Remove an index | DROP INDEX idx_name ON table_name; |
ALTER TABLE to add index | Add an index using ALTER TABLE | ALTER TABLE users ADD INDEX idx_created_at (created_at); |
Partial index | Index only part of a string column | CREATE INDEX idx_name_prefix ON products(name(10)); |
Descending index | Create an index in descending order (MySQL 8.0+) | CREATE INDEX idx_created_desc ON users(created_at DESC); |
Fulltext index | Create an index for full-text search | CREATE FULLTEXT INDEX idx_content ON articles(title, content); |
Spatial index | Create an index for spatial data | CREATE SPATIAL INDEX idx_location ON stores(location); |
Invisible index | Create an index that isn't used by the optimizer (MySQL 8.0+) | CREATE INDEX idx_test ON users(test_column) INVISIBLE; |
Functional index | Create an index on an expression (MySQL 8.0+) | CREATE INDEX idx_upper_email ON users((UPPER(email))); |
Transactions
Command | Description | Example |
---|---|---|
START TRANSACTION | Begin a new transaction | START TRANSACTION; |
BEGIN | Begin a new transaction (alternative syntax) | BEGIN; |
COMMIT | Save changes and end transaction | COMMIT; |
ROLLBACK | Discard changes and end transaction | ROLLBACK; |
SAVEPOINT | Create a point to which you can roll back | SAVEPOINT my_savepoint; |
ROLLBACK TO SAVEPOINT | Roll back to a specific savepoint | ROLLBACK TO SAVEPOINT my_savepoint; |
RELEASE SAVEPOINT | Delete a savepoint | RELEASE SAVEPOINT my_savepoint; |
SET TRANSACTION | Set transaction characteristics | SET TRANSACTION ISOLATION LEVEL READ COMMITTED; |
Complete transaction example | Full transaction with error handling | START TRANSACTION; INSERT INTO orders (customer_id, total) VALUES (123, 456.78); -- Get the new order ID SET @order_id = LAST_INSERT_ID(); INSERT INTO order_items (order_id, product_id, quantity, price) VALUES (@order_id, 1, 2, 100.00), (@order_id, 2, 1, 256.78); -- If everything is OK, commit the transaction COMMIT; -- On error, you would do: -- ROLLBACK; |
Setting isolation level | Change the transaction isolation level | -- Available levels: -- READ UNCOMMITTED -- READ COMMITTED -- REPEATABLE READ (default in MySQL) -- SERIALIZABLE SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; |
Read-only transaction | Set a transaction to read-only mode | START TRANSACTION READ ONLY; |
Check autocommit status | See if autocommit is enabled | SELECT @@autocommit; |
Disable autocommit | Turn off automatic commits | SET autocommit = 0; |
Enable autocommit | Turn on automatic commits | SET autocommit = 1; |
Stored Procedures and Functions
Command | Description | Example |
---|---|---|
CREATE PROCEDURE | Create a stored procedure | DELIMITER // CREATE PROCEDURE get_customers(IN country_filter VARCHAR(50)) BEGIN SELECT * FROM customers WHERE country = country_filter; END // DELIMITER ; |
CALL | Execute a stored procedure | CALL get_customers('USA'); |
DROP PROCEDURE | Delete a stored procedure | DROP PROCEDURE get_customers; |
CREATE FUNCTION | Create a stored function | DELIMITER // CREATE FUNCTION calculate_discount( price DECIMAL(10,2), discount_percent INT ) RETURNS DECIMAL(10,2) DETERMINISTIC BEGIN DECLARE discounted_price DECIMAL(10,2); SET discounted_price = price * (1 - discount_percent/100); RETURN discounted_price; END // DELIMITER ; |
Using a stored function | Use a function in SQL queries | SELECT name, price, calculate_discount(price, 10) AS discounted_price FROM products; |
DROP FUNCTION | Delete a stored function | DROP FUNCTION calculate_discount; |
Procedure with OUT parameter | Create a procedure that returns a value | DELIMITER // CREATE PROCEDURE get_product_count( IN category_id INT, OUT product_count INT ) BEGIN SELECT COUNT(*) INTO product_count FROM products WHERE products.category_id = category_id; END // DELIMITER ; |
Using OUT parameters | Call a procedure and get the OUT value | SET @count = 0; CALL get_product_count(5, @count); SELECT @count; |
Procedure with INOUT parameter | Create a procedure with an INOUT parameter | DELIMITER // CREATE PROCEDURE double_value( INOUT value INT ) BEGIN SET value = value * 2; END // DELIMITER ; |
Using INOUT parameters | Call a procedure with an INOUT parameter | SET @val = 5; CALL double_value(@val); SELECT @val; -- Will return 10 |
Procedure with error handling | Create a procedure with error handling | DELIMITER // CREATE PROCEDURE insert_product( IN p_name VARCHAR(100), IN p_price DECIMAL(10,2) ) BEGIN DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ROLLBACK; SELECT 'Error occurred. Transaction rolled back.' AS message; END; START TRANSACTION; INSERT INTO products (name, price) VALUES (p_name, p_price); COMMIT; SELECT 'Product added successfully.' AS message; END // DELIMITER ; |
Show procedures/functions | List stored procedures or functions | -- View all procedures in the current database SHOW PROCEDURE STATUS WHERE Db = DATABASE(); -- View all functions in the current database SHOW FUNCTION STATUS WHERE Db = DATABASE(); |
View procedure/function code | See the source code of a procedure or function | -- View procedure code SHOW CREATE PROCEDURE procedure_name; -- View function code SHOW CREATE FUNCTION function_name; |
Using conditionals | Use IF-ELSE statements in a procedure | DELIMITER // CREATE PROCEDURE apply_discount( IN order_id INT ) BEGIN DECLARE total DECIMAL(10,2); SELECT total_amount INTO total FROM orders WHERE id = order_id; IF total > 1000 THEN UPDATE orders SET discount = 0.15 WHERE id = order_id; ELSEIF total > 500 THEN UPDATE orders SET discount = 0.1 WHERE id = order_id; ELSE UPDATE orders SET discount = 0.05 WHERE id = order_id; END IF; END // DELIMITER ; |
Triggers
Command | Description | Example |
---|---|---|
CREATE TRIGGER | Create a trigger that runs before or after an event | DELIMITER // CREATE TRIGGER after_order_insert AFTER INSERT ON orders FOR EACH ROW BEGIN UPDATE customers SET order_count = order_count + 1 WHERE id = NEW.customer_id; END // DELIMITER ; |
BEFORE INSERT trigger | Run before a new row is inserted | DELIMITER // CREATE TRIGGER before_user_insert BEFORE INSERT ON users FOR EACH ROW BEGIN SET NEW.email = LOWER(NEW.email); SET NEW.created_at = NOW(); END // DELIMITER ; |
AFTER INSERT trigger | Run after a new row is inserted | DELIMITER // CREATE TRIGGER after_order_insert AFTER INSERT ON orders FOR EACH ROW BEGIN INSERT INTO order_log (order_id, action, timestamp) VALUES (NEW.id, 'Order created', NOW()); END // DELIMITER ; |
BEFORE UPDATE trigger | Run before a row is updated | DELIMITER // CREATE TRIGGER before_product_update BEFORE UPDATE ON products FOR EACH ROW BEGIN SET NEW.updated_at = NOW(); IF NEW.price != OLD.price THEN INSERT INTO price_history (product_id, old_price, new_price, changed_at) VALUES (OLD.id, OLD.price, NEW.price, NOW()); END IF; END // DELIMITER ; |
AFTER UPDATE trigger | Run after a row is updated | DELIMITER // CREATE TRIGGER after_status_update AFTER UPDATE ON orders FOR EACH ROW BEGIN IF NEW.status != OLD.status THEN INSERT INTO order_status_log (order_id, old_status, new_status, changed_at) VALUES (OLD.id, OLD.status, NEW.status, NOW()); END IF; END // DELIMITER ; |
BEFORE DELETE trigger | Run before a row is deleted | DELIMITER // CREATE TRIGGER before_user_delete BEFORE DELETE ON users FOR EACH ROW BEGIN INSERT INTO deleted_users (id, name, email, deleted_at) VALUES (OLD.id, OLD.name, OLD.email, NOW()); END // DELIMITER ; |
AFTER DELETE trigger | Run after a row is deleted | DELIMITER // CREATE TRIGGER after_product_delete AFTER DELETE ON products FOR EACH ROW BEGIN DELETE FROM product_tags WHERE product_id = OLD.id; END // DELIMITER ; |
DROP TRIGGER | Delete a trigger | DROP TRIGGER before_user_insert; |
SHOW TRIGGERS | List all triggers | SHOW TRIGGERS; -- Or for specific database/table SHOW TRIGGERS WHERE `Table` = 'users'; |
Combined triggers | Create triggers for multiple events | -- You need separate triggers for each event -- This example shows how to create two related triggers DELIMITER // CREATE TRIGGER before_inventory_insert BEFORE INSERT ON inventory FOR EACH ROW BEGIN SET NEW.last_updated = NOW(); END // CREATE TRIGGER before_inventory_update BEFORE UPDATE ON inventory FOR EACH ROW BEGIN SET NEW.last_updated = NOW(); END // DELIMITER ; |
Trigger with conditions | Create a trigger that executes conditionally | DELIMITER // CREATE TRIGGER check_minimum_price BEFORE UPDATE ON products FOR EACH ROW BEGIN IF NEW.price < 0 THEN SET NEW.price = 0; END IF; END // DELIMITER ; |
Trigger with error handling | Create a trigger that signals an error | DELIMITER // CREATE TRIGGER prevent_price_decrease BEFORE UPDATE ON products FOR EACH ROW BEGIN IF NEW.price < OLD.price THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Price cannot be decreased'; END IF; END // DELIMITER ; |
Backup and Restore
Command | Description | Example |
---|---|---|
mysqldump basic | Backup a database to a SQL file | mysqldump -u username -p database_name > backup.sql |
mysqldump multiple databases | Backup multiple databases | mysqldump -u username -p --databases db1 db2 > backup.sql |
mysqldump all databases | Backup all databases | mysqldump -u username -p --all-databases > backup.sql |
mysqldump specific tables | Backup specific tables in a database | mysqldump -u username -p database_name table1 table2 > backup.sql |
mysqldump with options | Backup with specific options | mysqldump -u username -p --single-transaction --routines --triggers database_name > backup.sql |
mysqldump exclude tables | Backup excluding specific tables | mysqldump -u username -p database_name --ignore-table=database_name.table_to_ignore > backup.sql |
mysqldump compress output | Compress the backup file | mysqldump -u username -p database_name | gzip > backup.sql.gz |
Restore from mysqldump | Restore a database from a SQL file | mysql -u username -p database_name < backup.sql |
Restore compressed backup | Restore from a compressed SQL file | gunzip < backup.sql.gz | mysql -u username -p database_name |
mysqlpump | Enhanced backup utility (MySQL 5.7+) | mysqlpump -u username -p --parallel-schemas=4 database_name > backup.sql |
mysqldump with progress | Show progress during backup | mysqldump -u username -p --verbose database_name > backup.sql |
Binary log backup | Backup binary logs for point-in-time recovery | mysqlbinlog binlog.000001 binlog.000002 > binlog_backup.sql |
Physical backup with MySQL Enterprise Backup | Commercial hot backup solution | mysqlbackup --user=username --password=password --backup-dir=/backup backup |
Physical backup with Percona XtraBackup | Open-source hot backup solution | xtrabackup --backup --target-dir=/backup |
Restore with Percona XtraBackup | Restore from XtraBackup | xtrabackup --prepare --target-dir=/backup xtrabackup --copy-back --target-dir=/backup |
Backup with encryption | Create an encrypted backup | mysqldump -u username -p database_name | openssl enc -aes-256-cbc -salt -out backup.sql.enc |
Scheduled backup with cron | Setup automatic backups | # Add to crontab (crontab -e): 0 2 * * * mysqldump -u username -p"password" database_name | gzip > /backup/db_$(date +\%Y\%m\%d).sql.gz |
Importing and Exporting Data
Command | Description | Example |
---|---|---|
LOAD DATA INFILE | Import data from a CSV/text file | LOAD DATA INFILE '/path/to/data.csv' INTO TABLE table_name FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n' IGNORE 1 ROWS; -- Skip header row |
LOAD DATA LOCAL INFILE | Import from a file on the client side | LOAD DATA LOCAL INFILE '/path/to/local/data.csv' INTO TABLE table_name FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n'; |
SELECT INTO OUTFILE | Export data to a CSV/text file | SELECT * FROM table_name INTO OUTFILE '/path/to/export.csv' FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n'; |
mysqldump for export | Export data to a SQL file | mysqldump -u username -p database_name table_name > table_export.sql |
mysqlimport | Import data using the command-line tool | mysqlimport -u username -p --fields-terminated-by=',' \ --lines-terminated-by='\n' database_name /path/to/data.csv |
Export to JSON | Export query results as JSON | SELECT JSON_OBJECT( 'id', id, 'name', name, 'email', email ) AS json_data FROM users INTO OUTFILE '/path/to/users.json'; |
Import from JSON | Import JSON data | -- Create a table for JSON data CREATE TABLE json_import (data JSON); -- Load JSON file LOAD DATA INFILE '/path/to/data.json' INTO TABLE json_import; |
mysqldump with tab format | Export as tab-delimited files | mysqldump -u username -p --tab=/path/to/directory database_name |
Export with column headers | Include headers in the export | -- First, output column headers SELECT 'id', 'name', 'email' UNION ALL SELECT id, name, email FROM users INTO OUTFILE '/path/to/users_with_headers.csv' FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n'; |
Import XML | Import data from XML format | -- Using LOAD XML (MySQL 5.5+) LOAD XML INFILE '/path/to/data.xml' INTO TABLE table_name ROWS IDENTIFIED BY 'row'; |
Export XML | Export data in XML format | -- Select with XML functions SELECT CONCAT( '<user>', '<id>', id, '</id>', '<name>', name, '</name>', '<email>', email, '</email>', '</user>' ) AS xml_data FROM users INTO OUTFILE '/path/to/users.xml'; |
Export with mysqldump and --xml | Export database or table in XML format | mysqldump -u username -p --xml database_name table_name > table_export.xml |
Import and transform data | Import data with transformations | LOAD DATA INFILE '/path/to/data.csv' INTO TABLE users FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n' (@col1, @col2, @col3) SET id = @col1, name = UPPER(@col2), email = LOWER(@col3), created_at = NOW(); |
Import from Excel | Import data from Excel | -- Save Excel as CSV first, then: LOAD DATA INFILE '/path/to/excel_export.csv' INTO TABLE table_name FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\r\n' -- Excel uses CRLF IGNORE 1 ROWS; |
sql_mode for importing | Set SQL mode for importing data | -- Relax constraints during import SET SESSION sql_mode=''; -- Load data LOAD DATA INFILE '/path/to/data.csv' INTO TABLE table_name FIELDS TERMINATED BY ','; |
User Privileges and Permissions
Command | Description | Example |
---|---|---|
GRANT basic | Grant privileges to a user | GRANT SELECT, INSERT, UPDATE ON database_name.* TO 'username'@'localhost'; |
GRANT all privileges | Grant all privileges on a database | GRANT ALL PRIVILEGES ON database_name.* TO 'username'@'localhost'; |
GRANT with IDENTIFIED BY | Create user and grant privileges | GRANT ALL PRIVILEGES ON database_name.* TO 'username'@'localhost' IDENTIFIED BY 'password'; |
GRANT on specific table | Grant privileges on a specific table | GRANT SELECT, UPDATE ON database_name.table_name TO 'username'@'localhost'; |
GRANT on specific columns | Grant privileges on specific columns | GRANT SELECT (id, name), UPDATE (name) ON database_name.table_name TO 'username'@'localhost'; |
GRANT with GRANT OPTION | Allow user to grant their privileges to others | GRANT SELECT ON database_name.* TO 'username'@'localhost' WITH GRANT OPTION; |
REVOKE basic | Remove privileges from a user | REVOKE INSERT ON database_name.* FROM 'username'@'localhost'; |
REVOKE all privileges | Remove all privileges | REVOKE ALL PRIVILEGES ON database_name.* FROM 'username'@'localhost'; |
REVOKE grant option | Remove the ability to grant privileges | REVOKE GRANT OPTION ON database_name.* FROM 'username'@'localhost'; |
SHOW GRANTS | View privileges of a user | SHOW GRANTS FOR 'username'@'localhost'; |
Global privileges | Grant server-level privileges | GRANT CREATE USER ON *.* TO 'admin'@'localhost'; |
Common privilege types | Most frequently used privilege types | -- Data privileges GRANT SELECT, INSERT, UPDATE, DELETE ON db.* TO 'user'@'localhost'; -- Structure privileges GRANT CREATE, ALTER, DROP ON db.* TO 'user'@'localhost'; -- Admin privileges GRANT CREATE USER, RELOAD, PROCESS ON *.* TO 'admin'@'localhost'; |
User roles (MySQL 8.0+) | Create and manage roles | -- Create role CREATE ROLE 'app_read', 'app_write'; -- Grant privileges to role GRANT SELECT ON app_db.* TO 'app_read'; GRANT INSERT, UPDATE, DELETE ON app_db.* TO 'app_write'; -- Grant role to users GRANT 'app_read', 'app_write' TO 'app_user'@'localhost'; -- Set default role SET DEFAULT ROLE 'app_read', 'app_write' TO 'app_user'@'localhost'; |
Activate role | Activate a granted role (MySQL 8.0+) | SET ROLE 'app_read'; |
View user information | See users and their attributes | SELECT User, Host FROM mysql.user; |
Limit resource usage | Set user resource limits | CREATE USER 'username'@'localhost' WITH MAX_QUERIES_PER_HOUR 1000 MAX_UPDATES_PER_HOUR 500 MAX_CONNECTIONS_PER_HOUR 200 MAX_USER_CONNECTIONS 10; |
Managing Connections and Sessions
Command | Description | Example |
---|---|---|
SHOW PROCESSLIST | Display list of active connections | SHOW PROCESSLIST; |
SHOW FULL PROCESSLIST | Display complete active connections with full query text | SHOW FULL PROCESSLIST; |
KILL CONNECTION | Terminate a specific connection | KILL CONNECTION 1234; |
KILL QUERY | Terminate a specific query without killing the connection | KILL QUERY 1234; |
SET SESSION | Set a variable for the current session only | SET SESSION sort_buffer_size = 10485760; |
SHOW SESSION VARIABLES | Display all session variables | SHOW SESSION VARIABLES; |
SHOW SESSION VARIABLES LIKE | Display session variables matching a pattern | SHOW SESSION VARIABLES LIKE 'max%'; |
SHOW SESSION STATUS | Display session status information | SHOW SESSION STATUS; |
SET SESSION SQL_MODE | Change SQL mode for current session | SET SESSION SQL_MODE = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES'; |
SELECT CONNECTION_ID() | Get the connection ID for the current connection | SELECT CONNECTION_ID(); |
GET LOCK | Get named lock (for coordination between sessions) | SELECT GET_LOCK('my_lock', 10); |
RELEASE LOCK | Release a named lock | SELECT RELEASE_LOCK('my_lock'); |
IS_FREE_LOCK | Check if a named lock is free | SELECT IS_FREE_LOCK('my_lock'); |
SHOW ENGINE INNODB STATUS | Display detailed InnoDB status including transactions and locks | SHOW ENGINE INNODB STATUS; |
SET wait_timeout | Set the timeout for interactive connections | SET SESSION wait_timeout = 28800; |
SET interactive_timeout | Set the timeout for interactive connections | SET SESSION interactive_timeout = 28800; |
Configuration Files and Server Settings
Configuration | Description | Example |
---|---|---|
Main configuration file | Primary MySQL configuration file locations | Linux: /etc/mysql/my.cnf or /etc/my.cnf Windows: C:\ProgramData\MySQL\MySQL Server X.Y\my.ini macOS: /usr/local/mysql/etc/my.cnf |
SHOW VARIABLES | Display all MySQL server variables | SHOW VARIABLES; |
SHOW VARIABLES LIKE | Display server variables matching a pattern | SHOW VARIABLES LIKE 'innodb%'; |
SHOW GLOBAL VARIABLES | Display global server variables | SHOW GLOBAL VARIABLES; |
SET GLOBAL | Modify global server variables (requires privileges) | SET GLOBAL max_connections = 500; |
SET PERSIST (MySQL 8.0+) | Set variable persistently (survives restart) | SET PERSIST max_connections = 500; |
SHOW STATUS | Display server status variables | SHOW STATUS; |
SHOW GLOBAL STATUS | Display global status information | SHOW GLOBAL STATUS; |
Common my.cnf sections | Main configuration file sections | [client] - Client settings [mysqld] - Server settings [mysqldump] - Backup tool settings [mysql] - MySQL client settings |
InnoDB configuration | Common InnoDB settings | [mysqld] innodb_buffer_pool_size = 1G innodb_log_file_size = 256M innodb_flush_log_at_trx_commit = 1 innodb_flush_method = O_DIRECT |
Performance settings | Common performance-related parameters | [mysqld] max_connections = 500 table_open_cache = 4000 query_cache_size = 0 # Disabled in MySQL 8.0+ max_allowed_packet = 64M |
Character set configuration | Configure default character sets | [mysqld] character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci [client] default-character-set = utf8mb4 |
Binary log settings | Configure binary logging | [mysqld] log_bin = mysql-bin binlog_format = ROW expire_logs_days = 14 max_binlog_size = 100M |
Logging settings | Configure error and general logs | [mysqld] log_error = /var/log/mysql/error.log general_log = 0 general_log_file = /var/log/mysql/mysql.log slow_query_log = 1 slow_query_log_file = /var/log/mysql/slow.log long_query_time = 2 |
mysqld --verbose --help | Display all server options and default values | mysqld --verbose --help |
RESET PERSIST (MySQL 8.0+) | Remove a persisted variable setting | RESET PERSIST max_connections; |
Performance Optimization
Command/Technique | Description | Example |
---|---|---|
EXPLAIN | Analyze a query's execution plan | EXPLAIN SELECT * FROM users WHERE email = 'user@example.com'; |
EXPLAIN FORMAT=JSON | Detailed execution plan in JSON format | EXPLAIN FORMAT=JSON SELECT * FROM users u JOIN orders o ON u.id = o.user_id WHERE u.status = 'active'; |
EXPLAIN ANALYZE (MySQL 8.0+) | Get execution plan with actual performance metrics | EXPLAIN ANALYZE SELECT * FROM users JOIN orders ON users.id = orders.user_id WHERE users.created_at > '2022-01-01'; |
SHOW INDEX | Display indexes for a table | SHOW INDEX FROM users; |
CREATE INDEX | Create an index on columns | CREATE INDEX idx_email ON users(email); |
SHOW PROFILE | Get detailed execution information for a query | SET profiling = 1; -- Run your query SELECT * FROM large_table WHERE complex_condition; -- Get the profile SHOW PROFILES; SHOW PROFILE FOR QUERY 1; |
SHOW STATUS for query cache | Check query cache status (pre-MySQL 8.0) | SHOW STATUS LIKE 'Qcache%'; |
ANALYZE TABLE | Update index statistics for better query plans | ANALYZE TABLE users; |
OPTIMIZE TABLE | Defragment a table to improve performance | OPTIMIZE TABLE orders; |
Covering indexes | Create indexes that include all columns needed by a query | CREATE INDEX idx_user_email_status ON users(email, status); |
Compound indexes | Create indexes on multiple columns for better filtering | CREATE INDEX idx_last_first_email ON users(last_name, first_name, email); |
LIMIT optimization | Use LIMIT for large result sets | -- Instead of selecting all rows SELECT * FROM large_table LIMIT 1000; |
Avoid SELECT * | Select only needed columns to reduce I/O | -- Instead of: SELECT * FROM users; -- Use: SELECT id, name, email FROM users; |
Join optimization | Ensure JOINed columns are indexed | CREATE INDEX idx_user_id ON orders(user_id); |
Partitioning | Divide large tables into manageable pieces | CREATE TABLE sales ( id INT NOT NULL, sale_date DATE NOT NULL, amount DECIMAL(10,2), PRIMARY KEY (id, sale_date) ) PARTITION BY RANGE (YEAR(sale_date)) ( PARTITION p0 VALUES LESS THAN (2020), PARTITION p1 VALUES LESS THAN (2021), PARTITION p2 VALUES LESS THAN (2022), PARTITION p3 VALUES LESS THAN MAXVALUE ); |
Slow query log | Enable slow query logging to find problematic queries | SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 1; -- Log queries longer than 1 second SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log'; |
Performance Schema | Use Performance Schema for monitoring | -- Find queries with full table scans SELECT digest_text, count_star, sum_timer_wait FROM performance_schema.events_statements_summary_by_digest WHERE digest_text LIKE '%select%' ORDER BY sum_timer_wait DESC LIMIT 10; |
sys Schema (MySQL 5.7+) | Use simplified views over Performance Schema | -- Show top 10 queries by average execution time SELECT * FROM sys.statements_with_runtimes_in_95th_percentile LIMIT 10; |
Error Handling
Command/Concept | Description | Example |
---|---|---|
SHOW WARNINGS | Display warnings from the last statement | SHOW WARNINGS; |
SHOW ERRORS | Display errors from the last statement | SHOW ERRORS; |
SHOW COUNT(*) WARNINGS | Display the number of warnings | SHOW COUNT(*) WARNINGS; |
SIGNAL | Raise error conditions from stored procedures | DELIMITER // CREATE PROCEDURE check_negative_balance(IN account_id INT, IN amount DECIMAL(10,2)) BEGIN DECLARE current_balance DECIMAL(10,2); SELECT balance INTO current_balance FROM accounts WHERE id = account_id; IF current_balance - amount < 0 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Insufficient funds', MYSQL_ERRNO = 1001; END IF; END // DELIMITER ; |
SQLSTATE values | Standard error condition identifiers | '00000': Success '01000': Warning '23000': Integrity constraint violation '42000': Syntax error or access rule violation '45000': Custom user-defined error |
DECLARE ... HANDLER | Handle errors in stored procedures | DELIMITER // CREATE PROCEDURE transfer_funds( IN from_account INT, IN to_account INT, IN amount DECIMAL(10,2) ) BEGIN DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ROLLBACK; SELECT 'An error occurred. Transaction rolled back.' AS message; END; START TRANSACTION; UPDATE accounts SET balance = balance - amount WHERE id = from_account; UPDATE accounts SET balance = balance + amount WHERE id = to_account; COMMIT; SELECT 'Transfer completed successfully.' AS message; END // DELIMITER ; |
Handler types | Different handler actions in stored procedures | DECLARE CONTINUE HANDLER FOR SQLEXCEPTION -- Continue execution DECLARE EXIT HANDLER FOR SQLEXCEPTION -- Exit current block DECLARE UNDO HANDLER FOR SQLEXCEPTION -- Undo work (rarely used) |
Handler condition types | Different ways to specify error conditions | -- By SQLSTATE DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' ... -- By MySQL error code DECLARE CONTINUE HANDLER FOR 1062 ... -- Duplicate key -- By named condition DECLARE duplicate_key CONDITION FOR 1062; DECLARE CONTINUE HANDLER FOR duplicate_key ... |
GET DIAGNOSTICS | Get detailed error information (MySQL 5.7+) | DELIMITER // CREATE PROCEDURE p() BEGIN DECLARE err_msg TEXT; DECLARE err_no INT; -- Execute a statement INSERT INTO table_with_unique_constraint VALUES(1, 'Duplicate'); -- Get error info GET DIAGNOSTICS CONDITION 1 err_no = MYSQL_ERRNO, err_msg = MESSAGE_TEXT; SELECT err_no, err_msg; END // DELIMITER ; |
IGNORE keyword | Ignore errors for a statement | -- Insert will continue even if some rows cause duplicate key errors INSERT IGNORE INTO users (id, name) VALUES (1, 'John'), (2, 'Jane'); |
Error log location | Find MySQL error log location | SHOW VARIABLES LIKE 'log_error'; |
RESIGNAL | Pass error along after handling it | DELIMITER // CREATE PROCEDURE validate_and_transfer(from_acc INT, to_acc INT, amount DECIMAL(10,2)) BEGIN DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN -- Log the error INSERT INTO error_log (error_time, procedure_name) VALUES (NOW(), 'validate_and_transfer'); -- Re-raise the error RESIGNAL; END; -- Procedure body CALL transfer_funds(from_acc, to_acc, amount); END // DELIMITER ; |
Working with Dates and Times
Function/Command | Description | Example |
---|---|---|
NOW() | Current date and time | SELECT NOW(); -- 2023-07-19 15:30:45 |
CURDATE() | Current date only | SELECT CURDATE(); -- 2023-07-19 |
CURTIME() | Current time only | SELECT CURTIME(); -- 15:30:45 |
DATE_FORMAT() | Format a date/time value | SELECT DATE_FORMAT(NOW(), '%W, %M %d, %Y'); -- Wednesday, July 19, 2023 SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s'); -- 2023-07-19 15:30:45 |
STR_TO_DATE() | Convert string to date using format | SELECT STR_TO_DATE('July 19, 2023', '%M %d, %Y'); -- 2023-07-19 |
UNIX_TIMESTAMP() | Convert to Unix timestamp (seconds since 1970-01-01) | SELECT UNIX_TIMESTAMP(NOW()); -- 1689778245 |
FROM_UNIXTIME() | Convert Unix timestamp to datetime | SELECT FROM_UNIXTIME(1689778245); -- 2023-07-19 15:30:45 |
DATEDIFF() | Difference between two dates in days | SELECT DATEDIFF('2023-07-30', '2023-07-19'); -- 11 |
TIMEDIFF() | Difference between two times | SELECT TIMEDIFF('15:30:45', '10:15:30'); -- 05:15:15 |
DATE_ADD() / ADDDATE() | Add time interval to a date | SELECT DATE_ADD(NOW(), INTERVAL 7 DAY); -- 7 days from now SELECT DATE_ADD('2023-07-19', INTERVAL 3 MONTH); -- 2023-10-19 |
DATE_SUB() / SUBDATE() | Subtract time interval from a date | SELECT DATE_SUB(NOW(), INTERVAL 7 DAY); -- 7 days ago SELECT DATE_SUB('2023-07-19', INTERVAL 3 MONTH); -- 2023-04-19 |
TIMESTAMPDIFF() | Difference between dates in specified unit | SELECT TIMESTAMPDIFF(MONTH, '2022-01-01', '2023-07-19'); -- 18 SELECT TIMESTAMPDIFF(HOUR, '2023-07-19 10:00:00', '2023-07-19 15:30:45'); -- 5 |
DAYNAME() | Get name of weekday | SELECT DAYNAME('2023-07-19'); -- Wednesday |
MONTHNAME() | Get name of month | SELECT MONTHNAME('2023-07-19'); -- July |
EXTRACT() | Extract part from date | SELECT EXTRACT(YEAR FROM '2023-07-19'); -- 2023 SELECT EXTRACT(MONTH FROM '2023-07-19'); -- 7 SELECT EXTRACT(DAY FROM '2023-07-19'); -- 19 |
YEAR() , MONTH() , DAY() | Extract year, month, day from date | SELECT YEAR('2023-07-19'); -- 2023 SELECT MONTH('2023-07-19'); -- 7 SELECT DAY('2023-07-19'); -- 19 |
HOUR() , MINUTE() , SECOND() | Extract hour, minute, second from time | SELECT HOUR('15:30:45'); -- 15 SELECT MINUTE('15:30:45'); -- 30 SELECT SECOND('15:30:45'); -- 45 |
LAST_DAY() | Last day of the month for a date | SELECT LAST_DAY('2023-07-19'); -- 2023-07-31 |
MAKEDATE() | Create a date from year and day of year | SELECT MAKEDATE(2023, 200); -- 2023-07-19 (200th day of 2023) |
DATE() | Extract the date part from a datetime | SELECT DATE('2023-07-19 15:30:45'); -- 2023-07-19 |
TIME() | Extract the time part from a datetime | SELECT TIME('2023-07-19 15:30:45'); -- 15:30:45 |
Common date format specifiers | Format patterns for DATE_FORMAT() and STR_TO_DATE() | %Y - Year (4 digits) %y - Year (2 digits) %M - Month name (January..December) %m - Month (01..12) %d - Day of month (01..31) %H - Hour (00..23) %h - Hour (01..12) %i - Minutes (00..59) %s - Seconds (00..59) %W - Weekday name (Sunday..Saturday) |
String Functions
Function | Description | Example |
---|---|---|
CONCAT() | Concatenate strings | SELECT CONCAT('Hello', ' ', 'World'); -- 'Hello World' |
CONCAT_WS() | Concatenate with separator | SELECT CONCAT_WS('-', 'Hello', 'World', '2023'); -- 'Hello-World-2023' |
LENGTH() | String length in bytes | SELECT LENGTH('Hello'); -- 5 |
CHAR_LENGTH() | String length in characters | SELECT CHAR_LENGTH('Hello😊'); -- 6 (handles multi-byte chars) |
LEFT() | Extract leftmost characters | SELECT LEFT('Hello World', 5); -- 'Hello' |
RIGHT() | Extract rightmost characters | SELECT RIGHT('Hello World', 5); -- 'World' |
SUBSTRING() / SUBSTR() | Extract a substring | SELECT SUBSTRING('Hello World', 7, 5); -- 'World' SELECT SUBSTRING('Hello World', 7); -- 'World' (to end) |
LOCATE() / POSITION() | Find position of substring | SELECT LOCATE('World', 'Hello World'); -- 7 SELECT POSITION('World' IN 'Hello World'); -- 7 |
INSTR() | Find position of substring | SELECT INSTR('Hello World', 'World'); -- 7 |
REPLACE() | Replace all occurrences of a substring | SELECT REPLACE('Hello World', 'World', 'MySQL'); -- 'Hello MySQL' |
TRIM() | Remove leading and trailing spaces | SELECT TRIM(' Hello World '); -- 'Hello World' |
LTRIM() , RTRIM() | Remove leading or trailing spaces | SELECT LTRIM(' Hello'); -- 'Hello' SELECT RTRIM('Hello '); -- 'Hello' |
LOWER() / LCASE() | Convert to lowercase | SELECT LOWER('Hello WORLD'); -- 'hello world' |
UPPER() / UCASE() | Convert to uppercase | SELECT UPPER('Hello world'); -- 'HELLO WORLD' |
REPEAT() | Repeat a string | SELECT REPEAT('MySQL ', 3); -- 'MySQL MySQL MySQL ' |
REVERSE() | Reverse a string | SELECT REVERSE('Hello'); -- 'olleH' |
INSERT() | Insert substring at position | SELECT INSERT('Hello World', 7, 5, 'MySQL'); -- 'Hello MySQL' |
LPAD() | Left-pad a string to a length | SELECT LPAD('42', 5, '0'); -- '00042' |
RPAD() | Right-pad a string to a length | SELECT RPAD('Hello', 10, '.'); -- 'Hello.....' |
SPACE() | Return a string of spaces | SELECT CONCAT('Hello', SPACE(5), 'World'); -- 'Hello World' |
FORMAT() | Format a number | SELECT FORMAT(12345.678, 2); -- '12,345.68' (locale-dependent) |
FIELD() | Return position of first match | SELECT FIELD('b', 'a', 'b', 'c'); -- 2 |
FIND_IN_SET() | Find position in comma-separated list | SELECT FIND_IN_SET('b', 'a,b,c,d'); -- 2 |
SUBSTRING_INDEX() | Return substring before n occurrences of delimiter | SELECT SUBSTRING_INDEX('www.mysql.com', '.', 2); -- 'www.mysql' SELECT SUBSTRING_INDEX('www.mysql.com', '.', -2); -- 'mysql.com' |
REGEXP / RLIKE | Pattern matching using regular expressions | SELECT 'MySQL' REGEXP '^My'; -- 1 (true) SELECT * FROM users WHERE name REGEXP '^A[a-z]*$'; |
REGEXP_REPLACE() (MySQL 8.0+) | Replace substrings using regex | SELECT REGEXP_REPLACE('Hello 123 World', '[0-9]+', 'number'); -- 'Hello number World' |
REGEXP_LIKE() (MySQL 8.0+) | Pattern matching with regex | SELECT REGEXP_LIKE('abc@example.com', '^[a-z]+@[a-z]+\.[a-z]+$'); -- 1 |
Numeric and Mathematical Functions
Function | Description | Example |
---|---|---|
ABS() | Absolute value | SELECT ABS(-15); -- 15 |
CEILING() / CEIL() | Round up to nearest integer | SELECT CEILING(15.4); -- 16 |
FLOOR() | Round down to nearest integer | SELECT FLOOR(15.7); -- 15 |
ROUND() | Round to nearest integer or decimal places | SELECT ROUND(15.4); -- 15 SELECT ROUND(15.7); -- 16 SELECT ROUND(15.678, 2); -- 15.68 |
TRUNCATE() | Truncate to specified number of decimal places | SELECT TRUNCATE(15.678, 2); -- 15.67 SELECT TRUNCATE(15.678, 0); -- 15 |
MOD() / % | Modulo operation (remainder) | SELECT MOD(15, 4); -- 3 SELECT 15 % 4; -- 3 |
POW() / POWER() | Raise to the power of | SELECT POW(2, 3); -- 8 SELECT POWER(2, 3); -- 8 |
SQRT() | Square root | SELECT SQRT(16); -- 4 |
EXP() | e raised to the power of | SELECT EXP(1); -- 2.718281828459045 |
LN() | Natural logarithm | SELECT LN(2.718281828459045); -- 1 |
LOG() | Natural logarithm or logarithm to base | SELECT LOG(2.718281828459045); -- 1 SELECT LOG(10, 100); -- 2 (log base 10 of 100) |
LOG2() | Log base 2 | SELECT LOG2(8); -- 3 |
LOG10() | Log base 10 | SELECT LOG10(100); -- 2 |
PI() | Value of π | SELECT PI(); -- 3.141593 |
SIN() , COS() , TAN() | Trigonometric functions (radians) | SELECT SIN(PI()/2); -- 1 SELECT COS(PI()); -- -1 SELECT TAN(PI()/4); -- 1 |
ASIN() , ACOS() , ATAN() | Inverse trigonometric functions | SELECT ASIN(1); -- 1.5707963267949 (π/2) SELECT ACOS(-1); -- 3.141593 (π) SELECT ATAN(1); -- 0.7853981633974483 (π/4) |
DEGREES() | Convert radians to degrees | SELECT DEGREES(PI()); -- 180 |
RADIANS() | Convert degrees to radians | SELECT RADIANS(180); -- 3.141593 |
SIGN() | Return sign of a number (-1, 0, 1) | SELECT SIGN(-15); -- -1 SELECT SIGN(0); -- 0 SELECT SIGN(15); -- 1 |
RAND() | Random floating-point value (0 to 1) | SELECT RAND(); -- 0.123456789 SELECT RAND(42); -- Seeded random number |
Random integer in range | Generate a random integer between min and max | SELECT FLOOR(RAND() * 10); -- 0 to 9 SELECT FLOOR(RAND() * 10) + 1; -- 1 to 10 SELECT FLOOR(RAND() * (max-min+1)) + min; -- min to max |
DIV | Integer division | SELECT 15 DIV 2; -- 7 (integer division) |
/ | Floating-point division | SELECT 15 / 2; -- 7.5 (floating-point division) |
CONV() | Convert numbers between bases | SELECT CONV('A', 16, 10); -- 10 (hex to decimal) SELECT CONV('1010', 2, 10); -- 10 (binary to decimal) SELECT CONV('10', 10, 16); -- A (decimal to hex) |
BIN() | Convert to binary string | SELECT BIN(10); -- '1010' |
OCT() | Convert to octal string | SELECT OCT(10); -- '12' |
HEX() | Convert to hexadecimal string | SELECT HEX(255); -- 'FF' |
FORMAT() | Format number to specified decimal places | SELECT FORMAT(12345.678, 2); -- '12,345.68' |
JSON Functions
Function | Description | Example |
---|---|---|
JSON_ARRAY() | Create a JSON array | SELECT JSON_ARRAY(1, 'abc', NULL, TRUE); -- [1, "abc", null, true] |
JSON_OBJECT() | Create a JSON object | SELECT JSON_OBJECT('id', 87, 'name', 'carrot'); -- {"id": 87, "name": "carrot"} |
JSON_QUOTE() | Quote a string as a JSON value | SELECT JSON_QUOTE('hello'); -- "hello" |
JSON_CONTAINS() | Check if JSON document contains specific value | SELECT JSON_CONTAINS('{"a": 1, "b": 2}', '1', '$.a'); -- 1 (true) |
JSON_EXTRACT() | Extract value from JSON document | SELECT JSON_EXTRACT('{"id": 14, "name": "Aztec"}', '$.name'); -- "Aztec" |
-> operator (shorthand) | Extract value from JSON document (MySQL 5.7.9+) | SELECT '{"id": 14, "name": "Aztec"}' -> '$.name'; -- "Aztec" |
->> operator (unquoted) | Extract value from JSON document without quotes (MySQL 5.7.13+) | SELECT '{"id": 14, "name": "Aztec"}' ->> '$.name'; -- Aztec |
JSON_VALID() | Check if value is valid JSON | SELECT JSON_VALID('{"a": 1}'); -- 1 (true) SELECT JSON_VALID('{"a":'); -- 0 (false) |
Administrative Commands
Command | Description | Example |
---|---|---|
SHOW DATABASES | List all databases on the server | SHOW DATABASES; |
SHOW TABLES | List all tables in the current database | SHOW TABLES; |
SHOW CREATE TABLE | Show the CREATE statement for a table | SHOW CREATE TABLE users; |
SHOW COLUMNS | Show all columns in a table | SHOW COLUMNS FROM users; |
DESCRIBE / DESC | Display structure of a table (shorthand for SHOW COLUMNS) | DESCRIBE users; DESC users; |
SHOW INDEX | Show all indexes in a table | SHOW INDEX FROM users; |
SHOW PROCESSLIST | Show active database connections and queries | SHOW PROCESSLIST; |
SHOW STATUS | Show server status variables | SHOW STATUS; SHOW STATUS LIKE 'Threads%'; |
SHOW VARIABLES | Show server configuration variables | SHOW VARIABLES; SHOW VARIABLES LIKE 'max_connections'; |
SHOW ENGINES | Show available storage engines | SHOW ENGINES; |
SHOW ENGINE INNODB STATUS | Show detailed InnoDB status | SHOW ENGINE INNODB STATUS; |
SHOW GRANTS | Show privileges for a user | SHOW GRANTS FOR 'user'@'localhost'; |
SHOW MASTER STATUS | Show binary log status (for replication) | SHOW MASTER STATUS; |
SHOW SLAVE STATUS | Show replication slave status | SHOW SLAVE STATUS\G |
SHOW WARNINGS | Show warnings from the last statement | SHOW WARNINGS; |
SHOW ERRORS | Show errors from the last statement | SHOW ERRORS; |
FLUSH PRIVILEGES | Reload grant tables (after user changes) | FLUSH PRIVILEGES; |
FLUSH LOGS | Flush all logs | FLUSH LOGS; |
FLUSH TABLES | Close all tables and flush caches | FLUSH TABLES; |
OPTIMIZE TABLE | Defragment and optimize a table | OPTIMIZE TABLE users; |
ANALYZE TABLE | Analyze and store key distribution for a table | ANALYZE TABLE users; |
CHECK TABLE | Check table for errors | CHECK TABLE users; |
REPAIR TABLE | Repair a possibly corrupted table | REPAIR TABLE users; |
KILL | Terminate a database thread | KILL 123; -- Kill thread by ID KILL QUERY 123; -- Kill just a query |
Replication Basics
Command/Configuration | Description | Example |
---|---|---|
Master my.cnf settings | Configuration for replication master server | # In /etc/my.cnf or my.ini (master server) [mysqld] server-id = 1 log_bin = mysql-bin binlog_format = ROW # or MIXED, STATEMENT binlog_do_db = db_to_replicate # Optional: only replicate specific DB binlog_ignore_db = db_to_ignore # Optional: don't replicate specific DB |
Slave my.cnf settings | Configuration for replication slave server | # In /etc/my.cnf or my.ini (slave server) [mysqld] server-id = 2 # Must be unique relay-log = relay-bin read_only = 1 # Recommended for slave servers replicate_do_db = db_to_replicate # Optional replicate_ignore_db = db_to_ignore # Optional |
Creating replication user | Create user with replication privileges on master | -- On master server CREATE USER 'repl_user'@'slave_ip' IDENTIFIED BY 'password'; GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'slave_ip'; |
SHOW MASTER STATUS | Check binary log status on master | -- On master server SHOW MASTER STATUS; /* Output: +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000003 | 73 | test | | | +------------------+----------+--------------+------------------+-------------------+ */ |
Taking snapshot (simple method) | Create a backup of data for initial slave setup | # On master server mysqldump --all-databases --master-data=2 -u root -p > dump.sql # Transfer dump.sql to slave server scp dump.sql user@slave_ip:~/ # On slave server mysql -u root -p < dump.sql |
CHANGE MASTER TO | Configure slave to connect to master | -- On slave server CHANGE MASTER TO MASTER_HOST='master_ip', MASTER_USER='repl_user', MASTER_PASSWORD='password', MASTER_LOG_FILE='mysql-bin.000003', -- From SHOW MASTER STATUS MASTER_LOG_POS=73; -- From SHOW MASTER STATUS |
START SLAVE | Start replication on slave | -- On slave server START SLAVE; |
STOP SLAVE | Stop replication on slave | -- On slave server STOP SLAVE; |
SHOW SLAVE STATUS | Check replication status on slave | -- On slave server SHOW SLAVE STATUS\G /* Look for: Slave_IO_Running: Yes Slave_SQL_Running: Yes */ |
GTID Replication (MySQL 5.6+) | Global Transaction Identifier based replication | # On both master and slave in my.cnf: [mysqld] gtid_mode = ON enforce_gtid_consistency = ON # Then on slave: CHANGE MASTER TO MASTER_HOST='master_ip', MASTER_USER='repl_user', MASTER_PASSWORD='password', MASTER_AUTO_POSITION=1; -- Use GTID instead of binary log position |
Skip a problematic transaction | When a slave encounters an error | -- On slave server (MySQL 5.7+) STOP SLAVE; SET GLOBAL sql_slave_skip_counter = 1; START SLAVE; -- For GTID replication (MySQL 5.7+) STOP SLAVE; SET @@GLOBAL.GTID_NEXT='specific_gtid_to_skip'; BEGIN; COMMIT; SET @@GLOBAL.GTID_NEXT='AUTOMATIC'; START SLAVE; |
Multi-source replication (MySQL 5.7+) | Slave replicates from multiple masters | -- On slave server CHANGE MASTER TO MASTER_HOST='master1_ip', MASTER_USER='repl_user1', MASTER_PASSWORD='password1', MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=73 FOR CHANNEL 'master1'; CHANGE MASTER TO MASTER_HOST='master2_ip', MASTER_USER='repl_user2', MASTER_PASSWORD='password2', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=120 FOR CHANNEL 'master2'; START SLAVE FOR CHANNEL 'master1'; START SLAVE FOR CHANNEL 'master2'; |
Reset replication | Reset slave or master state | -- On slave server STOP SLAVE; RESET SLAVE; -- Or RESET SLAVE ALL to remove all connection info -- On master server RESET MASTER; -- Deletes all binary logs |
Security Best Practices
Practice/Command | Description | Example |
---|---|---|
Use strong passwords | Create users with complex passwords | CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'Str0ng_P@ssw0rd!'; |
Principle of least privilege | Grant only required permissions to users | -- Instead of: GRANT ALL ON *.* TO 'user'@'localhost'; -- Better: GRANT SELECT, INSERT, UPDATE, DELETE ON app_db.* TO 'app_user'@'localhost'; GRANT SELECT ON app_db.sensitive_table TO 'reporting_user'@'localhost'; |
Use roles (MySQL 8.0+) | Group privileges into roles for easier management | CREATE ROLE 'app_read', 'app_write'; GRANT SELECT ON app_db.* TO 'app_read'; GRANT INSERT, UPDATE, DELETE ON app_db.* TO 'app_write'; GRANT 'app_read' TO 'reporting_user'@'localhost'; GRANT 'app_read', 'app_write' TO 'admin_user'@'localhost'; |
Remove anonymous users | Delete anonymous user accounts | -- Check for anonymous users SELECT user, host FROM mysql.user WHERE user = ''; -- Remove anonymous users DELETE FROM mysql.user WHERE user = ''; FLUSH PRIVILEGES; |
Remove test database | Drop the default test database | DROP DATABASE test; DELETE FROM mysql.db WHERE db = 'test' OR db LIKE 'test\\_%'; FLUSH PRIVILEGES; |
Restrict remote access | Limit access to specific hosts | -- Create users with specific host patterns CREATE USER 'app_user'@'192.168.1.%' IDENTIFIED BY 'password'; -- Or secure the MySQL port in firewall -- iptables -A INPUT -p tcp --dport 3306 -s 192.168.1.0/24 -j ACCEPT -- iptables -A INPUT -p tcp --dport 3306 -j DROP |
Enable TLS/SSL | Encrypt connections between clients and server | # In my.cnf [mysqld] ssl_ca=ca.pem ssl_cert=server-cert.pem ssl_key=server-key.pem # Create user requiring SSL CREATE USER 'secure_user'@'%' IDENTIFIED BY 'password' REQUIRE SSL; |
Use authentication plugins | Better password security (MySQL 8.0+) | # MySQL 8.0+ uses caching_sha2_password by default # For clients that don't support it: CREATE USER 'app_user'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password'; |
Password validation | Enable password policy plugin | # In my.cnf [mysqld] plugin-load-add=validate_password.so validate_password_policy=MEDIUM # Check settings SHOW VARIABLES LIKE 'validate_password%'; |
Audit user activity | Enable audit log plugin (MySQL Enterprise) | # In my.cnf [mysqld] plugin-load-add=audit_log.so audit_log_file=/var/log/mysql/audit.log audit_log_policy=ALL |
Lock user accounts | Temporarily disable user access | -- MySQL 8.0+ ALTER USER 'app_user'@'localhost' ACCOUNT LOCK; -- Re-enable later ALTER USER 'app_user'@'localhost' ACCOUNT UNLOCK; |
Password expiration | Force regular password changes | -- Expire password after 90 days ALTER USER 'app_user'@'localhost' PASSWORD EXPIRE INTERVAL 90 DAY; -- Expire password now ALTER USER 'app_user'@'localhost' PASSWORD EXPIRE; |
Run with least privileges | Run MySQL server as unprivileged user | # Create mysql user if not exists useradd -r -g mysql mysql # Ensure MySQL data directory permissions chown -R mysql:mysql /var/lib/mysql |
Disable LOCAL INFILE | Prevent loading data from client files | # In my.cnf [mysqld] local-infile=0 # Check setting SHOW VARIABLES LIKE 'local_infile'; |
Prevent LOAD DATA | Restrict loading data from server files | # Limit secure_file_priv to a specific directory # In my.cnf [mysqld] secure_file_priv=/var/mysql/secure_uploads # Or disable completely secure_file_priv=NULL # Check setting SHOW VARIABLES LIKE 'secure_file_priv'; |
Regular backups | Encrypt sensitive backup data | # Using encryption for backups mysqldump --all-databases | openssl enc -aes-256-cbc -salt > backup.sql.enc # Decrypt openssl enc -d -aes-256-cbc -in backup.sql.enc > backup.sql |
Skip networking | Disable network access for local-only instances | # In my.cnf [mysqld] skip-networking socket=/var/run/mysqld/mysqld.sock |
Monitor user access | Regularly review user accounts and privileges | -- List all users SELECT user, host FROM mysql.user; -- Review user privileges SELECT * FROM mysql.user WHERE user = 'app_user'; |
Common Server Commands
Command | Description | Example |
---|---|---|
Start MySQL server | Start the MySQL service | # Linux (systemd) sudo systemctl start mysql # Linux (init.d) sudo service mysql start # Windows net start mysql # macOS sudo launchctl load -F /Library/LaunchDaemons/com.oracle.oss.mysql.mysqld.plist |
Stop MySQL server | Stop the MySQL service | # Linux (systemd) sudo systemctl stop mysql # Linux (init.d) sudo service mysql stop # Windows net stop mysql # macOS sudo launchctl unload -F /Library/LaunchDaemons/com.oracle.oss.mysql.mysqld.plist |
Restart MySQL server | Restart the MySQL service | # Linux (systemd) sudo systemctl restart mysql # Linux (init.d) sudo service mysql restart # Windows net stop mysql && net start mysql # macOS sudo launchctl unload -F /Library/LaunchDaemons/com.oracle.oss.mysql.mysqld.plist sudo launchctl load -F /Library/LaunchDaemons/com.oracle.oss.mysql.mysqld.plist |
Check MySQL status | Check if MySQL server is running | # Linux (systemd) sudo systemctl status mysql # Linux (init.d) sudo service mysql status # Windows sc query mysql # macOS launchctl list | grep mysql |
MySQL client login | Connect to the MySQL server | # Basic login mysql -u root -p # Specify host and port mysql -h hostname -P 3306 -u username -p # Specify database mysql -u username -p database_name |
MySQL client options | Useful command line options | # Execute SQL from command line mysql -u root -p -e "SELECT VERSION();" # Vertical output format mysql -u root -p -e "SELECT * FROM users LIMIT 2" --vertical # Batch mode (tab-separated, non-interactive) mysql -u root -p --batch -e "SELECT * FROM users LIMIT 2" # XML output mysql -u root -p -e "SELECT * FROM users LIMIT 2" --xml |
MySQL backup | Backup databases using mysqldump | # Backup single database mysqldump -u root -p database_name > backup.sql # Backup multiple databases mysqldump -u root -p --databases db1 db2 > backup.sql # Backup all databases mysqldump -u root -p --all-databases > full_backup.sql # Backup structure only (no data) mysqldump -u root -p --no-data database_name > schema.sql |
MySQL restore | Restore from backup | # Restore a database mysql -u root -p database_name < backup.sql # Restore multiple databases mysql -u root -p < backup.sql |
MySQL config files | Common configuration file locations | # Linux /etc/my.cnf /etc/mysql/my.cnf /etc/mysql/mysql.conf.d/mysqld.cnf # Windows C:\ProgramData\MySQL\MySQL Server x.y\my.ini # macOS /usr/local/mysql/etc/my.cnf /etc/my.cnf |
MySQL logs | Common log file locations | # Find error log location mysql -u root -p -e "SHOW VARIABLES LIKE 'log_error';" # Common error log locations # Linux /var/log/mysql/error.log # Windows C:\ProgramData\MySQL\MySQL Server x.y\Data\hostname.err |
Reset root password | Reset forgotten root password | # Stop MySQL server sudo systemctl stop mysql # Start in safe mode sudo mysqld_safe --skip-grant-tables --skip-networking & # Connect without password mysql -u root # Set new password mysql> USE mysql; mysql> UPDATE user SET authentication_string=PASSWORD('new_password') WHERE User='root'; mysql> FLUSH PRIVILEGES; mysql> exit; # Restart server normally sudo systemctl restart mysql |
Import large files | Efficiently import large SQL files | # Using source command mysql -u root -p mysql> USE database_name; mysql> source /path/to/large_file.sql; # Using shell pipe pv large_file.sql | mysql -u root -p database_name |
MySQL secure installation | Secure a new MySQL installation | sudo mysql_secure_installation |
MySQL command history | View and manage MySQL client command history | # View history file cat ~/.mysql_history # Clear history rm ~/.mysql_history touch ~/.mysql_history |
Get MySQL version | Check MySQL server version | # From command line mysql -V mysqladmin -V # From MySQL client SELECT VERSION(); |
Version Differences
MySQL Version | Major Features/Changes | Notes |
---|---|---|
MySQL 8.0 |
| -- JSON functions SELECT JSON_TABLE(...); -- Window functions SELECT name, salary, AVG(salary) OVER (PARTITION BY department) AS dept_avg FROM employees; -- Common Table Expressions (CTE) WITH RECURSIVE cte AS ( SELECT 1 AS n UNION ALL SELECT n + 1 FROM cte WHERE n < 5 ) SELECT * FROM cte; |
MySQL 5.7 |
| -- JSON data type CREATE TABLE users ( id INT PRIMARY KEY, data JSON ); -- Generated columns CREATE TABLE circle ( radius DOUBLE, area DOUBLE AS (PI() * radius * radius) STORED ); |
MySQL 5.6 |
| -- EXPLAIN for non-SELECT EXPLAIN UPDATE users SET status = 'active' WHERE id = 123; -- Online ALTER TABLE ALTER TABLE users ADD INDEX idx_email (email), ALGORITHM=INPLACE, LOCK=NONE; |
MySQL 5.5 |
| -- SIGNAL error handling CREATE PROCEDURE check_value(value INT) BEGIN IF value < 0 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Value cannot be negative'; END IF; END; |
Migration compatibility issues |
| # 5.7 to 8.0 authentication plugin compatibility CREATE USER 'user'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password'; # Check SQL mode SELECT @@sql_mode; # Check reserved keywords SELECT 'group' FROM users; -- Error in 8.0, must use backticks SELECT `group` FROM users; -- Correct in 8.0 |
Version-specific syntax |
| -- MySQL 8.0 only SELECT * FROM table1 EXCEPT SELECT * FROM table2; -- TABLE statement (8.0+) TABLE users; -- Shorthand for SELECT * FROM users -- 5.7+ JSON functions SELECT JSON_EXTRACT(data, '$.name') FROM users; |