Getting Started
Connect to MySQL
The mysql client is the standard CLI for MySQL. Always use -p (no space after) so the password is prompted securely rather than visible in shell history. -h sets the host, -P (capital) sets the port. \s prints connection status. Use -e to run one-off queries in scripts.
# connect to local server (prompt for password)
mysql -u root -p
# connect to a remote host on a custom port
mysql -h 192.168.1.100 -P 3307 -u admin -p
# connect directly to a specific database
mysql -u root -p mydb
# non-interactive: run a query and exit
mysql -u root -p -e "SELECT VERSION();"
# show server status inside the client
\s
SELECT VERSION(), CURRENT_USER, DATABASE();Database Management
Use utf8mb4 (not utf8) to support full Unicode including emoji — MySQL's utf8 is a 3-byte subset that cannot store all characters. utf8mb4_unicode_ci is the recommended collation for correct sorting. IF EXISTS/IF NOT EXISTS prevent errors in scripts. DROP DATABASE removes all tables and data instantly.
# list all databases
SHOW DATABASES;
# create a database with charset and collation
CREATE DATABASE mydb
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
# switch to a database
USE mydb;
# show the current database
SELECT DATABASE();
# drop a database (irreversible)
DROP DATABASE IF EXISTS mydb;
# alter a database's charset
ALTER DATABASE mydb CHARACTER SET utf8mb4;Show & Describe Objects
SHOW commands are MySQL-specific introspection tools. DESCRIBE gives a quick column overview; SHOW CREATE TABLE gives the full DDL you can reuse. Append \G instead of ; for vertical output — much more readable for wide rows like SHOW CREATE TABLE.
# list tables in the current database
SHOW TABLES;
# show table structure (columns, types, keys)
DESCRIBE users;
# equivalent
SHOW COLUMNS FROM users;
# show create statement for a table
SHOW CREATE TABLE users\G
# list indexes on a table
SHOW INDEX FROM users;
# show stored procedures / functions
SHOW PROCEDURE STATUS WHERE Db = 'mydb';
SHOW FUNCTION STATUS WHERE Db = 'mydb';
# list triggers
SHOW TRIGGERS\GServer Status & Variables
MySQL variables have SESSION (current connection) and GLOBAL scopes. SET GLOBAL changes the running server but resets on restart — persist settings in my.cnf instead. @@var reads values. SHOW STATUS exposes runtime counters (connections, uptime, throughput) useful for monitoring.
# view a system variable
SHOW VARIABLES LIKE 'max_connections';
SHOW VARIABLES LIKE 'version%';
# view session vs global variable
SELECT @@session.sql_mode, @@global.sql_mode;
# set a variable for the current session
SET sql_mode = 'STRICT_TRANS_TABLES';
SET @@session.foreign_key_checks = 0;
# set globally (needs SUPER/privilege, persists until restart)
SET GLOBAL max_connections = 200;
# show server status counters
SHOW STATUS LIKE 'Threads%';
SHOW STATUS LIKE 'Uptime';Comments & Statement Basics
MySQL supports three comment styles: -- (requires a trailing space), /* */ blocks, and # to end of line. /*! ... */ is a special executable comment — code inside runs only on MySQL and is ignored by other SQL engines, useful for portable schema files. \G executes and displays results vertically.
-- single-line comment (note the space after --)
SELECT 1; -- inline comment
/* multi-line
comment block */
SELECT 2;
# hash-style comment (MySQL-specific, to end of line)
SELECT 3;
# MySQL executable comments: run only on MySQL
SELECT 1 /*!50100 , 2 */; /* the part runs on MySQL >= 5.1 */
# statements end with semicolon; \G ends and prints vertically
SELECT * FROM users\GConfiguration File (my.cnf)
my.cnf (Linux) / my.ini (Windows) holds persistent server and client settings organized in sections: [mysqld] for the server, [client]/[mysql] for the client. innodb_buffer_pool_size is the single most important tuning knob for InnoDB (typically 50-75% of RAM). After editing, restart the server. Use mysql --help or SHOW VARIABLES to verify.
# /etc/my.cnf or ~/.my.cnf (Linux/macOS)
# C:\ProgramData\MySQL\MySQL Server 8.0\my.ini (Windows)
[mysqld]
port = 3306
datadir = /var/lib/mysql
max_connections = 200
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
innodb_buffer_pool_size = 2G
slow_query_log = 1
long_query_time = 2
[client]
default-character-set = utf8mb4
[mysql]
prompt = \u@\h [\d]>\_DDL Operations
Create Table
CREATE TABLE defines columns, types, constraints and table options. InnoDB is the default and recommended engine (supports transactions, row-level locking, foreign keys). BIGINT UNSIGNED for AUTO_INCREMENT avoids overflow. DECIMAL(p,s) is exact for money. ENUM validates against a fixed list. TIMESTAMP DEFAULT CURRENT_TIMESTAMP auto-fills on insert.
CREATE TABLE users (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(255) NOT NULL,
birth_date DATE NULL,
status ENUM('active','inactive','banned') NOT NULL DEFAULT 'active',
balance DECIMAL(10,2) NOT NULL DEFAULT 0.00,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
INDEX idx_email (email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;Alter Table
ALTER TABLE evolves schema without recreating data. ADD COLUMN with AFTER places it in a specific position (column order is cosmetic in MySQL). MODIFY changes type/default; RENAME COLUMN (8.0+) is cleaner than CHANGE. Large ALTER operations may rebuild and lock the table — use pt-online-schema-change or online DDL for big tables. RENAME TABLE is atomic.
# add a column
ALTER TABLE users
ADD COLUMN phone VARCHAR(20) NULL AFTER email;
# add multiple columns
ALTER TABLE users
ADD COLUMN first_name VARCHAR(50) NULL,
ADD COLUMN last_name VARCHAR(50) NULL;
# modify a column type
ALTER TABLE users
MODIFY COLUMN phone VARCHAR(30) NOT NULL;
# rename a column (MySQL 8+ preserves data)
ALTER TABLE users
RENAME COLUMN phone TO phone_number;
# rename a table
RENAME TABLE users TO members;
ALTER TABLE users RENAME TO members;Drop & Truncate Table
DROP TABLE removes the table entirely; TRUNCATE empties it but keeps the structure and resets AUTO_INCREMENT to its start value. TRUNCATE is faster than DELETE because it skips per-row deletion and logging, but it is DDL (cannot be rolled back, fires no triggers). Disable foreign_key_checks when truncating tables referenced by others.
# drop a table (removes structure and data)
DROP TABLE IF EXISTS old_logs;
# drop multiple tables
DROP TABLE IF EXISTS temp1, temp2;
# truncate: empty the table, keep structure, reset AUTO_INCREMENT
TRUNCATE TABLE session_data;
# truncate cannot be rolled back in some engines
# (InnoDB: TRUNCATE is DDL, implicitly commits)
SET foreign_key_checks = 0;
TRUNCATE TABLE child_table;
SET foreign_key_checks = 1;AUTO_INCREMENT
AUTO_INCREMENT generates sequential numbers for a primary key — each table may have only one. LAST_INSERT_ID() returns the id generated by the most recent INSERT in the current session (per-connection, safe for concurrent use). Gaps can appear after deletes, rollbacks, or inserts that specify explicit values. To reset, use ALTER TABLE ... AUTO_INCREMENT = n.
CREATE TABLE orders (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
amount DECIMAL(10,2)
);
# set the next auto-increment value
ALTER TABLE orders AUTO_INCREMENT = 1000;
# insert without specifying id
INSERT INTO orders (amount) VALUES (99.50);
# get the last inserted id
SELECT LAST_INSERT_ID();
# show current AUTO_INCREMENT value
SHOW TABLE STATUS LIKE 'orders'\GTable Constraints
Constraints enforce data integrity at the database level. InnoDB supports primary keys, UNIQUE, NOT NULL, CHECK (enforced since 8.0.16) and foreign keys. FOREIGN KEY ... ON DELETE CASCADE removes child rows when the parent is deleted; SET NULL nullifies them; RESTRICT/NO ACTION block deletion. Name constraints explicitly for easier management. Foreign keys require indexes on both columns.
CREATE TABLE orders (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_id INT UNSIGNED NOT NULL,
total DECIMAL(10,2) NOT NULL,
status VARCHAR(20) NOT NULL,
# unique constraint
CONSTRAINT uq_order_no UNIQUE (user_id, status),
# check constraint (MySQL 8.0.16+ enforced)
CONSTRAINT chk_total CHECK (total >= 0),
# foreign key with cascading actions
CONSTRAINT fk_orders_user
FOREIGN KEY (user_id) REFERENCES users(id)
ON DELETE CASCADE
ON UPDATE RESTRICT
) ENGINE=InnoDB;
# add a constraint later
ALTER TABLE orders
ADD CONSTRAINT chk_status CHECK (status IN ('paid','shipped','cancelled'));Temporary Tables
TEMPORARY tables exist only for the current session and are dropped automatically when it closes. They can shadow a real table of the same name, useful for safe refactoring or staging data. Two sessions can create temporary tables with the same name without conflict. They are not visible to other connections and are not written to the binlog by default.