MySQL Databases and Tables
Create a database, name its character set explicitly, then read the table back with `SHOW CREATE TABLE` - which shows every default MySQL filled in that you did not type, and is the only honest answer to what a table actually is.
Schemas and Data Guide 6 of 45 Beginner
- OSUbuntu 26.04 LTS (resolute)
- MySQL8.4.10-0ubuntu0.26.04.1
- EngineInnoDB (default)
- TimeAbout 14 min
- Reviewed27 August 2026
Written against the versions above. utf8mb4 and utf8mb4_0900_ai_ci are the 8.0+ defaults. On 5.7 the default was latin1, which is exactly why naming it explicitly is a habit worth having.
| Server Name | IP Address | OS | Roles | CPU | RAM | HDD |
|---|---|---|---|---|---|---|
| db-a01 | 192.168.0.81 | Ubuntu 26.04 LTS | Primary / Source / Replica Set Member 1 | 2 Core | 4 GB | 50 GB |
Before you start
- MySQL running on db-a01, reachable with
sudo mysql.
-
Create a database, and say what it is for
CREATE DATABASEon its own would work. Naming the character set and collation is the habit worth forming: it is metadata every table inherits, and changing it later means rewriting every table in the schema.utf8mb4 is real, four-byte Unicode. MySQL's older
utf8is three bytes and cannot store an emoji or several CJK characters - a genuine trap, and the reason the name has amb4on the end.bash Example session sudo mysql -e "CREATE DATABASE appdb CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci"sudo mysql --table -e "SHOW DATABASES"+--------------------+| Database |+--------------------+| appdb || information_schema || mysql || performance_schema || sys |+--------------------+Expected resultNo output from the create, then
appdbalongside the four system schemas.Success conditionYou have a database whose encoding you chose rather than inherited.
-
Read back what the server actually stored
SHOW CREATE DATABASEis the server's own account of the object, not an echo of what you typed. Get into the habit of trusting it over your memory of the statement.\Gprints it one field per line, which matters here because the create statement is long.bash Example session sudo mysql -e "SHOW CREATE DATABASE appdb\G"*************************** 1. row *************************** Database: appdbCreate Database: CREATE DATABASE `appdb` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */Expected resultA
CREATE DATABASEline carryingutf8mb4andutf8mb4_0900_ai_ci.Success conditionYou can confirm an object's real definition rather than assuming it.
-
Create a table with the column types you meant
Five columns, each chosen deliberately.
INT UNSIGNED AUTO_INCREMENT PRIMARY KEYis the standard surrogate key - unsigned because there is no such thing as customer minus four.VARCHAR(80)stores up to 80 characters, not bytes.DECIMAL(10,2)for money, neverFLOAT: decimal is exact, and a float cannot represent 0.10 precisely, which is how a balance drifts by a penny per transaction.TIMESTAMP ... DEFAULT CURRENT_TIMESTAMPlets the server fill the value so every row is stamped by the same clock.NOT NULLon name and email is a decision, and the next guide shows the server enforcing it.bash sudo mysql appdb -e "CREATE TABLE customers (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, name VARCHAR(80) NOT NULL, email VARCHAR(120) NOT NULL UNIQUE, credit DECIMAL(10,2) NOT NULL DEFAULT 0.00, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP)"Expected resultNo output. In SQL that is success.
Success conditionThe table exists with types chosen for what they hold.
-
See everything you did not type
This is the step to slow down on.
SHOW CREATE TABLEreturns the full definition including every default the server supplied.Look for what appeared on its own:
ENGINE=InnoDB, the table's ownDEFAULT CHARSETandCOLLATEinherited from the database, and a namedUNIQUE KEYon email - you wrote the wordUNIQUEinline and MySQL turned it into a named index, because in InnoDB a unique constraint is an index.That last point matters later: it is why the duplicate check in the next guide is fast, and why the same index serves lookups by email.
bash Example session sudo mysql appdb -e "SHOW CREATE TABLE customers\G"*************************** 1. row *************************** Table: customersCreate Table: CREATE TABLE `customers` ( `id` int unsigned NOT NULL AUTO_INCREMENT, `name` varchar(80) NOT NULL, `email` varchar(120) NOT NULL, `credit` decimal(10,2) NOT NULL DEFAULT '0.00', `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `email` (`email`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ciExpected resultThe full definition with
ENGINE=InnoDB, aPRIMARY KEY, and a namedUNIQUE KEYon email.Success conditionYou know what the server filled in for you and why the unique key is an index.
-
The short form, for when you only need the shape
DESCRIBEis the quick view: column, type, nullability, key, default, extra.Read the
Nullcolumn against what you declared.id,nameandemailsayNO; nothing else was constrained, socreditandcreated_atcarry their defaults instead.Extrashowsauto_incrementon id andDEFAULT_GENERATEDon the timestamp.Use
DESCRIBEto remind yourself of a shape andSHOW CREATE TABLEwhen the details matter.bash Example session sudo mysql --table appdb -e "DESCRIBE customers"+------------+---------------+------+-----+-------------------+-------------------+| Field | Type | Null | Key | Default | Extra |+------------+---------------+------+-----+-------------------+-------------------+| id | int unsigned | NO | PRI | NULL | auto_increment || name | varchar(80) | NO | | NULL | || email | varchar(120) | NO | UNI | NULL | || credit | decimal(10,2) | NO | | 0.00 | || created_at | timestamp | NO | | CURRENT_TIMESTAMP | DEFAULT_GENERATED |+------------+---------------+------+-----+-------------------+-------------------+Expected resultFive rows with
idasPRIandemailasUNI.Success conditionYou can read a table's shape at a glance.
Troubleshooting
ERROR 1049 (42000): Unknown database.Why: The database name is wrong, or you are on a different server than you think.
Fix:
SHOW DATABASESfirst, andSELECT @@hostnameif more than one server is in play.Emoji or some CJK characters store as
????.Why: The column or connection is on three-byte
utf8, notutf8mb4.Fix:
SHOW CREATE TABLEto check the table, andSTATUSto check the client connection. Both ends have to agree.Money values drift by a penny.
Why: The column is
FLOATorDOUBLE. Binary floating point cannot represent 0.10.Fix:
DECIMAL(10,2). Converting later means anALTER TABLEover every existing row.