MySQL Command Line
The mysql command-line client is the most direct way to interact with MySQL. It ships with every MySQL installation, works over SSH, supports scripting, and has zero GUI overhead. Mastering the CLI makes you faster at database work and is essential for server administration, CI/CD pipelines, and working on remote servers where no GUI is available.
Connecting to MySQL
The basic syntax for the mysql client is:
mysql [options] [database_name]
Flag | Long Form | Description |
|---|---|---|
-u | --user=name | MySQL username |
-p | --password | Prompt for password (never supply inline) |
-h | --host=name | Hostname or IP (default: localhost via socket) |
-P | --port=number | TCP port (default: 3306) |
-D | --database=name | Select database on connect |
-S | --socket=path | Connect via Unix socket file |
-e | --execute=stmt | Execute a statement and exit (non-interactive) |
--ssl-mode=REQUIRED | Require SSL/TLS for the connection |
# Connect to local MySQL as root (password prompt appears) mysql -u root -p # Connect and select a database immediately mysql -u appuser -p myapp_db # Connect to a remote server mysql -h db.example.com -P 3306 -u appuser -p myapp_db # Connect via Unix socket (fastest for localhost on Linux/macOS) mysql -u root -p -S /var/run/mysqld/mysqld.sock # Execute a single statement and exit (useful in shell scripts) mysql -u root -p -e "SHOW DATABASES;"
-pmypassword on the command line — it appears in shell history and system process listings. Always use -p alone for a prompt, or use a credentials file.Using a .my.cnf Credentials File
# Create ~/.my.cnf with your connection defaults # Add these lines to the file: # [client] # user=appuser # password=SecurePassword123! # host=localhost # database=myapp_db # Secure the file — readable only by your user chmod 600 ~/.my.cnf # Now connect without flags — credentials come from the file mysql
[client] section applies to all MySQL client programs including mysqldump and mysqlcheck. You can add a named section like [mysqldump] with different settings just for that tool.Essential mysql Commands
-- List all databases on the server SHOW DATABASES; -- Switch to a database USE myapp_db; -- Show which database is currently selected SELECT DATABASE(); -- List all tables in the current database SHOW TABLES; -- Show tables matching a pattern SHOW TABLES LIKE 'order%'; -- Describe a table (column names, types, constraints) DESCRIBE users; DESC users; -- Show the full CREATE TABLE statement SHOW CREATE TABLE users; -- List all indexes on a table SHOW INDEX FROM users; -- Show running queries and connections SHOW PROCESSLIST; -- Show server status variables SHOW STATUS LIKE 'Threads_connected'; -- Show server configuration variables SHOW VARIABLES LIKE 'max_connections';
Running SQL Script Files
# Method 1: Redirect from the shell (fastest, works in scripts) mysql -u appuser -p myapp_db < schema.sql # With verbose output to see each statement mysql -u root -p --verbose myapp_db < migration_001.sql # Capture output and errors to a log file mysql -u root -p myapp_db < migration.sql > migration.log 2>&1
-- Method 2: source command inside the mysql prompt source /path/to/migration.sql; -- Shorthand for source . /path/to/migration.sql
~/.my.cnf file so scripts run unattended without exposing credentials on the command line or in environment variables.Output Format Options
Flag | Effect |
|---|---|
--table (-t) | Force tabular output (default in interactive mode) |
--batch (-B) | Tab-separated values, no borders — good for scripting |
--silent (-s) | Suppress table headers and extra output |
--vertical (-E) | Print each row vertically — one field per line |
--html (-H) | Output as an HTML table |
--xml (-X) | Output as XML |
# Tab-separated (easy to process with awk or Python) mysql -u root -p --batch -e "SELECT id, email FROM users LIMIT 5;" myapp_db # Silent mode — just the value, no headers mysql -u root -p --silent --skip-column-names -e "SELECT COUNT(*) FROM users;" myapp_db
Multi-line Queries and the \\G Modifier
A query is not sent until you type a semicolon and press Enter. The prompt changes to
show context — -> means the statement is continuing.
End any query with \G instead of ; to display results vertically.
This is invaluable for tables with many columns or very wide values:
-- Vertical output with G SELECT * FROM users WHERE id = 1G
*************************** 1. row ***************************
id: 1
email: alice@example.com
first_name: Alice
last_name: Smith
created_at: 2024-01-15 09:00:00Shell Escape and External Editor
-- \! runs a shell command without leaving mysql \! ls /var/log/mysql/ \! date -- \e opens your $EDITOR to write the query, then executes on save \e
The \e command is useful for long complex queries — you get full editor
capabilities (search, syntax highlighting via plugins) and the query runs automatically
when you save and close the editor.
Built-in Commands Reference
Command | Shorthand | Description |
|---|---|---|
help | \h | Show help for mysql commands |
quit / exit | \q | Exit the mysql client |
clear | \c | Cancel the current partial query |
delimiter DELIM | \d DELIM | Change the statement delimiter |
ego | \G | Send query and display results vertically |
\p | Print the current query buffer without executing | |
source FILE | . | Execute SQL from a file |
status | \s | Show server and connection status |
system CMD | ! | Execute a shell command |
edit | \e | Open current query in $EDITOR |
tee FILE | \T | Copy all output to a log file |
notee | \t | Stop logging to the tee file |
Changing the Delimiter for Stored Procedures
The default delimiter is ;. When creating stored procedures or triggers, the
body contains semicolons. Change the delimiter temporarily so the client treats the whole
procedure as one statement:
DELIMITER // CREATE PROCEDURE GetUserCount() BEGIN SELECT COUNT(*) AS user_count FROM users; END // DELIMITER ; -- Call the procedure CALL GetUserCount();
Scripting with mysql in Bash
#!/bin/bash
# Count rows in a table — reads credentials from ~/.my.cnf
DB="myapp_db"
TABLE="users"
COUNT=$(mysql --silent --skip-column-names "$DB" -e "SELECT COUNT(*) FROM `$TABLE`;")
echo "Table $TABLE has $COUNT rows."
# Check if a migration has already run
APPLIED=$(mysql --silent --skip-column-names "$DB" -e "
SELECT COUNT(*) FROM migrations
WHERE migration_name = 'add_phone_column_to_users';
")
if [ "$APPLIED" -eq "0" ]; then
echo "Running migration..."
mysql "$DB" < add_phone_column_to_users.sql
mysql "$DB" -e "
INSERT INTO migrations (migration_name, applied_at)
VALUES ('add_phone_column_to_users', NOW());
"
else
echo "Migration already applied, skipping."
fiImporting and Exporting from the CLI
# Export a full database to a SQL dump mysqldump -u root -p myapp_db > myapp_db_backup.sql # Export compressed (much smaller files for large databases) mysqldump -u root -p myapp_db | gzip > myapp_db_backup.sql.gz # Export specific tables only mysqldump -u root -p myapp_db users orders > users_orders.sql # Export schema only — no INSERT statements mysqldump -u root -p --no-data myapp_db > schema_only.sql # Export with consistent snapshot (no table locks, InnoDB only) mysqldump -u root -p --single-transaction myapp_db > myapp_db_backup.sql # Import a SQL dump mysql -u root -p myapp_db < myapp_db_backup.sql # Import a compressed dump gunzip -c myapp_db_backup.sql.gz | mysql -u root -p myapp_db
--single-transaction to mysqldump when backing up InnoDB tables. It takes a consistent snapshot without locking tables, so your application can keep writing to the database during the backup.Connecting with SSL/TLS
# Require SSL for the connection mysql -u appuser -p --ssl-mode=REQUIRED --ssl-ca=/etc/mysql/ssl/ca.pem --ssl-cert=/etc/mysql/ssl/client-cert.pem --ssl-key=/etc/mysql/ssl/client-key.pem -h db.example.com myapp_db # Verify that SSL is active after connecting mysql> SHOW STATUS LIKE 'Ssl_cipher';
+---------------+-----------------------------+ | Variable_name | Value | +---------------+-----------------------------+ | Ssl_cipher | TLS_AES_256_GCM_SHA384 | +---------------+-----------------------------+
--ssl-ca for certificate verification.