INSERT adds new rows to a table. This is the first of the data-changing statements (DML).
CREATE TABLE customers (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) NOT NULL,
city VARCHAR(50) NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO customers (name, email, city)
VALUES ('Maya Shah', 'maya@example.com', 'Pune');
Query OK, 1 row affected
The message 1 row affected confirms one row was added. Look at it:
SELECT id, name, email, city, created_at IS NOT NULL AS has_created_at FROM customers;
+----+-----------+------------------+------+----------------+
| id | name | email | city | has_created_at |
+----+-----------+------------------+------+----------------+
| 1 | Maya Shah | maya@example.com | Pune | 1 |
+----+-----------+------------------+------+----------------+
1 row in set
You did not give id or created_at. MySQL used AUTO_INCREMENT for the first and DEFAULT CURRENT_TIMESTAMP for the second.
The syntax
INSERT INTO table_name (column1, column2, ...)
VALUES (value1, value2, ...);
- The column list says which columns you supply.
- The values are matched to the columns by position: the first value goes to the first column.
- The number of values must equal the number of columns.
- Text and dates go in single quotes. Numbers do not.
NULLis written without quotes.
Always write the column list
MySQL also allows this form:
INSERT INTO customers VALUES (NULL, 'Rohan Verma', 'rohan@example.com', 'Delhi', NOW());
It works only if you give a value for every column, in table order. If someone later adds a column or reorders them, your statement breaks or, worse, stores the wrong values in the wrong columns. Name the columns every time.
Columns you leave out
A column you leave out gets its default value. If it has no default and is NOT NULL, strict mode gives an error:
INSERT INTO customers (name, city) VALUES ('No Email', 'Kochi');
ERROR 1364 (HY000): Field 'email' doesn't have a default value
You can request the default explicitly with the DEFAULT keyword, or set a column to NULL on purpose:
INSERT INTO customers (name, email, city, created_at)
VALUES ('Sana Ali', 'sana@example.com', NULL, DEFAULT);
SELECT id, name, city FROM customers ORDER BY id;
+----+-------------+-------+
| id | name | city |
+----+-------------+-------+
| 1 | Maya Shah | Pune |
| 2 | Rohan Verma | Delhi |
| 3 | Sana Ali | NULL |
+----+-------------+-------+
3 rows in set
The SET form
MySQL also has an assignment-style syntax. It is MySQL-specific and not portable, but some find it readable for long rows:
INSERT INTO customers SET name = 'Tara Nair', email = 'tara@example.com', city = 'Kochi';
SELECT COUNT(*) AS total_customers FROM customers;
+-----------------+
| total_customers |
+-----------------+
| 4 |
+-----------------+
1 row in set
Rules to remember
- Match the order and the number of columns and values.
- Provide values for every
NOT NULLcolumn that has no default. - Do not insert into
AUTO_INCREMENTor generated columns unless you mean to (AUTO_INCREMENT). - When values come from a user, never paste them into the SQL text. Use prepared statements (Prepared Statements).
Dates and numbers
'2026-07-15', never '15/07/2026'. Write decimals with a dot (19.99). Do not put thousands separators in numbers.