Navigating Databases: Practical Use of USE and DESCRIBE Commands
Learn how to use MySQL USE and DESCRIBE safely when switching databases and inspecting table schemas.
Navigating Databases: Practical Use of USE and DESCRIBE Commands
USE and DESCRIBE are small MySQL commands, but they save real time when you are working in a shell, debugging someone else's database, or checking a schema before writing a query. They also prevent a very ordinary mistake: running the right SQL against the wrong database.
If you spend most of your day inside an application framework, it is easy to forget how useful the MySQL client can be. You connect, look around, inspect a table, and answer a question in a minute. The trick is to move carefully. Production databases often contain similarly named schemas, old tables, staging leftovers, and columns that do not quite mean what their names suggest.
What USE actually changes
The MySQL USE statement sets the default database for the current session. After you run it, unqualified table names are resolved against that database.
USE ecommerce_db;
From that point on, this query:
SELECT id, email FROM customers LIMIT 5;
means:
SELECT id, email FROM ecommerce_db.customers LIMIT 5;
The setting is session-specific. If you open another terminal, another database client tab, or reconnect after a timeout, you need to select the database again. MySQL's own documentation describes USE as choosing the named database as the default current database for subsequent statements, which is exactly how you should think about it.
Before switching, list what exists:
SHOW DATABASES;
Then select the target:
USE ecommerce_db;
Confirm where you are:
SELECT DATABASE();
That last check is worth the extra keystrokes before any destructive command. I have seen people keep three terminals open, all with similar prompts, then run a quick DELETE in the wrong one. A prompt plugin can help, but SELECT DATABASE(); is still the simplest truth check.
When to qualify table names instead
USE is convenient, but it is not always the clearest option. If you are comparing two databases, fully qualified names are safer:
SELECT COUNT(*) FROM production.users;
SELECT COUNT(*) FROM staging.users;
That removes ambiguity. It also makes pasted notes easier to understand later because the database name is in the query itself.
For migrations and one-off maintenance scripts, I prefer qualified names for anything risky. For interactive inspection, USE is fine as long as you keep checking context.
Database name case sensitivity can vary by operating system and MySQL configuration. Table name behavior can vary too. Do not rely on mixed-case names being portable. If your team uses lowercase schema and table names everywhere, keep following that convention.
What DESCRIBE shows you
DESCRIBE, often shortened to DESC, shows table structure. In everyday MySQL work, it answers questions like:
- What is the exact column name?
- Is this field nullable?
- What data type does this table actually use?
- Is there a primary key?
- Does the column auto-increment?
- What default value will an insert get?
Use it like this:
DESCRIBE customers;
or:
DESC customers;
A typical result looks like this:
+-------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+----------------+
| id | bigint unsigned | NO | PRI | NULL | auto_increment |
| email | varchar(255) | NO | UNI | NULL | |
| name | varchar(120) | YES | | NULL | |
| created_at | datetime | NO | | NULL | |
+-------------+------------------+------+-----+---------+----------------+
The Key column is a quick hint, not a full index report. PRI means primary key. UNI means the column is part of a unique index. MUL usually means the column is indexed but can contain repeated values. If you need complete index detail, use SHOW INDEX FROM customers; instead.
The MySQL parser treats DESCRIBE and EXPLAIN as synonyms in some contexts. In practice, people usually say DESCRIBE table_name when they want table structure and EXPLAIN SELECT ... when they want a query execution plan.
A realistic inspection workflow
Imagine you are debugging a failed checkout job. The application logs say Unknown column 'payment_status', but you are not sure which database the worker uses.
Start by connecting read-only if possible:
mysql -u readonly_user -p -h db.example.internal
Look for likely databases:
SHOW DATABASES;
Select the one the app should be using:
USE shop_production;
SELECT DATABASE();
List tables if you do not know the exact name:
SHOW TABLES LIKE '%order%';
Inspect the table:
DESCRIBE orders;
Maybe you find payment_state, not payment_status. Or maybe the column exists in staging but not production. That tells you whether the bug is a code/config mismatch, a missed migration, or simply the wrong database connection.
Before writing an INSERT, DESCRIBE is also useful:
DESC products;
If sku is NOT NULL, price is decimal(10,2), and created_at has no default, your insert needs to include those fields:
INSERT INTO products (sku, name, price, created_at)
VALUES ('MOUSE-USB-01', 'USB mouse', 19.99, NOW());
That is much better than guessing, failing, and then reading a long error message.
Use SHOW CREATE TABLE when DESCRIBE is not enough
DESCRIBE is quick, but it hides important details. It does not show foreign keys clearly, generated column expressions, full index definitions, partitioning, comments, or table options. When you need the real table definition, run:
SHOW CREATE TABLE orders\G
The \G output format is easier to read for wide results in the MySQL client. This command is especially useful before changing a table because it shows the exact DDL MySQL knows about.
For example, DESCRIBE may show that customer_id has MUL in the Key column. SHOW CREATE TABLE can tell you whether the index is only on customer_id or part of a composite index like (customer_id, created_at). That difference matters for performance and for deciding whether a new index is actually needed.
Common mistakes with USE and DESCRIBE
The first mistake is assuming USE changes anything outside your session. It does not. Your app, another terminal, and another user's connection keep their own context.
The second mistake is forgetting that table names can be qualified. If you run:
USE staging;
SELECT * FROM production.users LIMIT 5;
MySQL reads from production.users, not staging.users, because the query explicitly names the database. That is useful when intentional and dangerous when pasted carelessly.
The third mistake is treating DESCRIBE as a data-quality check. It tells you shape, not content. A column may be nullable even if the application never expects nulls. A varchar(255) field may contain empty strings. A decimal price column may contain old imported values with strange rounding. Use DESCRIBE to understand the schema, then sample the data separately:
SELECT payment_state, COUNT(*)
FROM orders
GROUP BY payment_state
ORDER BY COUNT(*) DESC;
The fourth mistake is running write statements in a session where you have not confirmed the database. Build the habit: SELECT DATABASE();, inspect, then write.
A safer habit for day-to-day MySQL work
When I open a MySQL shell on a shared environment, I follow a short rhythm:
SHOW DATABASES;
USE target_database;
SELECT DATABASE();
SHOW TABLES;
DESCRIBE important_table;
For anything risky, I add:
START TRANSACTION;
-- inspect or change a small number of rows
ROLLBACK;
Then I rerun the intended change only when I am sure. That transaction pattern does not fit every DDL statement or engine behavior, but for many data checks it gives you a chance to verify your WHERE clause before committing.
USE and DESCRIBE are not advanced commands, and that is the point. They give you orientation. USE tells MySQL where unqualified table names should point. DESCRIBE tells you what a table looks like before you query or change it. Used together, they make interactive database work calmer, faster, and less error-prone.