MySQL Tutorial 2
MySQL Tutorial 2
INSERT – learn how to use various forms of the INSERT statement to insert data into database
tables.
INSERT IGNORE – explain you the INSERT IGNORE statement that inserts rows into a table and
ignore rows that cause errors or exceptions.
UPDATE – learn how to use UPDATE statement and its options to update data in database tables.
UPDATE JOIN – show you how to perform cross table update using UPDATE JOIN statement
with INNER JOIN and LEFT JOIN .
DELETE – show you how to use the DELETE statement to remove data from one or more tables.
ON DELETE CASCADE – learn how to use ON DELETE CASCADE referential action for a foreign key
to delete data from a child table automatically when you delete data from a parent table.
DELETE JOIN – show you how to delete data from multiple tables.
REPLACE – learn how to insert or update data depends on whether data exists in the table or not.
Prepared Statement – show you how to use the prepared statement to execute a query.
First, you specify the table name and a list of comma-separated columns inside parentheses after
the INSERT INTO clause.
Then, you put a comma-separated values of the corresponding columns inside the parentheses followed
the VALUES keyword.
You need to have an INSERT privilege to use the INSERT statement.
Let’s create a new table named tasks for practicing the INSERT statement.
For example, if you want to insert a new task into the tasks table, you use the INSERT statement
as follows:
After executing the statement, MySQL returns a message to inform the number of rows affected. In this
case, one row were affected.
1 SELECT
2 *
3 FROM
4 tasks;
In this form, the value list of each row is separated by a comma. For example, to insert multiple rows into
the tasks table, you use the following statement:
If you specify the value of the corresponding column for all columns in the table, you can ignore the
column list in the INSERT statement as follows:
and
Notice that you don’t have to specify the value for auto-increment column e.g., taskid column because
MySQL generates value for the auto-increment column automatically.
First, create a new table named tasks_1 by copying the structure of the tasks table as follows:
Second, insert data from the tasks table into the tasks_1 table using the following INSERT statement:
Third, check the tasks_1 table to see if we actually copy it from the tasks table.
1 SELECT
2 *
3 FROM
4 tasks_1;
1 Error Code: 1062. Duplicate entry '4' for key 'PRIMARY' 0.016 sec
Because the row with the primary key task_id 4 already exists in the tasks table, the statement violates
the PRIMARY KEY constraint.
However, if you specify the ON DUPLICATE KEY UPDATE option in the INSERT statement, MySQL
will insert a new row or update the existing row with the new values.
For example, the following statement updates the existing row whose task_id is 4 with the new task_id
and subject.
1 SELECT
2 *
3 FROM
4 tasks;
The new row was not inserted. But the existing row with the task_id 4 was updated.
1 UPDATE tasks
2 SET
3 task_id = task_id + 1,
4 subject = 'Test ON DUPLICATE KEY UPDATE'
5 WHERE
6 task_id = 4;
For more information on the INSERT ON DUPLICATE KEY UPDATE statement, please check it out
the MySQL insert or update tutorial.
In this tutorial, we have shown you how to use various forms of the MySQL INSERT statement to insert
data into a table.
However, if you use the INSERT INGORE statement, the rows that cause the errors are ignored and the
remaining rows are inserted into the table.
Note that the INGORE clause is an extension of MySQL to the SQL standard.
MySQL INSERT IGNORE example
We will create a new table called subscribers for the demonstration.
The UNIQUE constraint ensures that no duplicate email exists in the email column.
The following statement inserts a new row into the subscribers table:
2 VALUES('[email protected]');
It worked as expected.
Let’s execute another statement that inserts two rows into the subscribers table:
It returns an error.
The server returned a message showing that one row is inserted and the other row is ignored.
1 1 row(s) affected, 1 warning(s): 1062 Duplicate entry '[email protected]' for key 'email' Records: 2 Duplicates: 1 Warnings: 1
If you use the SHOW WARNINGS statement, you will find the detail of the warning:
1 SHOW WARNINGS;
So when you use the INSERT INGORE statement, instead of issuing an error, MySQL issued a warning in
case an error occurs.
Querying data from subscribers table, you will find that only one row actually inserted and the rows
that cause an error was ignored.
However, if you use the INSERT INGORE statement, MySQL will issue a warning instead of an error. In
addition, it will try to adjust the values to make them valid before inserting.
Consider the following example.
In this table, the column s accepts only strings whose lengths are less than or equal 6.
MySQL issued the following error because the STRICT mode is on.
1 Error Code: 1406. Data too long for column 's' at row 1
Third, use the INSERT IGNORE statement to insert the same string.
MySQL truncated data before inserting it into the tokens table. In addition, it issues a warning.
In this tutorial, you have learned how to use the MySQL INSERT IGNORE statement to insert rows into a
table and ignore error for rows that cause errors.
MySQL UPDATE
Summary: updating data is one of the most important tasks when you work with the database. In this
tutorial, you will learn how to use the MySQL UPDATE statement to update data in a table.
First, specify the table name that you want to update data after the UPDATE keyword.
Second, the SET clause specifies which column that you want to modify and the new values. To
update multiple columns, you use a list comma-separated assignments. You supply the value in
each column’s assignment in the form of a literal value, an expression, or a subquery.
Third, specify which rows to be updated using a condition in the WHERE clause.
The WHERE clause is optional. If you omit the WHERE clause, the UPDATE statement will update all
rows in the table.
Notice that the WHERE clause is so important that you should not forget. Sometimes, you may want to
change just one row; However, you may forget the WHERE clause and accidentally updates all the rows in
the table.
1. The LOW_PRIORITY modifier instructs the UPDATE statement to delay the update until there is no
connection reading data from the table. The LOW_PRIORITY takes effect for the storage enginesthat
use table-level locking only, for example, MyISAM, MERGE, MEMORY.
2. The IGNORE modifier enables the UPDATE statement to continue updating rows even if errors
occurred. The rows that cause errors such as duplicate-key conflicts are not updated.
Let’s practice the UPDATE statement with some tables in the MySQL sample database.
MySQL UPDATE a single column example
In this example, we are going to update the email of Mary Patterson to the new
email [email protected] .
First, to make sure that we update the email successfully, we query Mary’s email from
the employees table using the following SELECT statement:
1 SELECT
2 firstname, lastname, email
3 FROM
4 employees
5 WHERE
6 employeeNumber = 1056;
Second, we can update Mary’s email to the new email [email protected] using
the UPDATE statement as the following query:
1 UPDATE employees
2 SET
3 email = '[email protected]'
4 WHERE
5 employeeNumber = 1056;
Because we just want to update one row, we use the WHERE clause to specify the row using the employee
number 1056 . The SET clause sets the value of the email column to the new email.
1 SELECT
2 firstname, lastname, email
3 FROM
4 employees
5 WHERE
6 employeeNumber = 1056;
1 UPDATE employees
2 SET
3 lastname = 'Hill',
4 email = '[email protected]'
5 WHERE
6 employeeNumber = 1056;
1 SELECT
2 firstname, lastname, email
3 FROM
4 employees
5 WHERE
6 employeeNumber = 1056;
For example, in the customers table, some customers do not have any sale representative. The value of
the column saleRepEmployeeNumber is NULL as follows:
1 SELECT
2 customername, salesRepEmployeeNumber
3 FROM
4 customers
5 WHERE
6 salesRepEmployeeNumber IS NULL;
To do this, we can select a random employee whose job title is Sales Rep from the employees table and
update it for the employees table.
This query selects a random employee from the employees table whose job title is the Sales Rep .
1 SELECT
2 employeeNumber
3 FROM
4 employees
5 WHERE
6 jobtitle = 'Sales Rep'
7 ORDER BY RAND()
8 LIMIT 1;
To update the sales representative employee number column in the customers table, we put the query
above in the SET clause of the UPDATE statement as follows:
1 UPDATE customers
2 SET
3 salesRepEmployeeNumber = (SELECT
4 employeeNumber
5 FROM
6 employees
7 WHERE
8 jobtitle = 'Sales Rep'
9 LIMIT 1)
10 WHERE
11 salesRepEmployeeNumber IS NULL;
If you query data from the employees table, you will see that every customer has a sales representative.
In other words, the following query returns no row.
1 SELECT
2 salesRepEmployeeNumber
3 FROM
4 customers
5 WHERE
6 salesRepEmployeeNumber IS NOT NULL;
In this tutorial, you have learned how to use MySQL UPDATE statement to update data in a database table.
First, you specify the main table ( T1 ) and the table that you want the main table to join to ( T2 )
after the UPDATE clause. Notice that you must specify at least one table after the UPDATE clause.
The data in the table that is not specified after the UPDATE clause is not updated.
Second, you specify a kind of join you want to use i.e., either INNER JOIN or LEFT JOIN and a join
condition. The JOIN clause must appear right after the UPDATE clause.
Third, you assign new values to the columns in T1 and/or T2 tables that you want to update.
Fourth, the condition in the WHERE clause allows you to specify which rows to update.
If you follow the UPDATE statement tutorial, you notice that there is another way to update data cross-
table using the following syntax:
1 UPDATE T1, T2
2 SET T1.c2 = T2.c2,
3 T2.c3 = expr
4 WHERE T1.c1 = T2.c1 AND condition
This UPDATE statement works the same as UPDATE JOIN with implicit INNER JOIN clause. It means you
can rewrite the above statement as follows:
1 UPDATE T1,T2
2 INNER JOIN T2 ON T1.C1 = T2.C1
3 SET T1.C2 = T2.C2,
4 T2.C3 = expr
5 WHERE condition
Let’s take a look at some examples of using the UPDATE JOIN statement to having a better
understanding.
The employees table stores employee data with employee id, name, performance, and salary.
The following statements create and load data in the empdb sample database:
1 CREATE DATABASE IF NOT EXISTS empdb;
2
3 USE empdb;
4
5 -- create tables
6 CREATE TABLE merits (
7 performance INT(11) NOT NULL,
8 percentage FLOAT NOT NULL,
9 PRIMARY KEY (performance)
10 );
11
12 CREATE TABLE employees (
13 emp_id INT(11) NOT NULL AUTO_INCREMENT,
14 emp_name VARCHAR(255) NOT NULL,
15 performance INT(11) DEFAULT NULL,
16 salary FLOAT DEFAULT NULL,
17 PRIMARY KEY (emp_id),
18 CONSTRAINT fk_performance FOREIGN KEY (performance)
19 REFERENCES merits (performance)
20 );
21 -- insert data for merits table
22 INSERT INTO merits(performance,percentage)
23 VALUES(1,0),
24 (2,0.01),
25 (3,0.03),
26 (4,0.05),
27 (5,0.08);
28 -- insert data for employees table
29 INSERT INTO employees(emp_name,performance,salary)
30 VALUES('Mary Doe', 1, 50000),
31 ('Cindy Smith', 3, 65000),
32 ('Sue Greenspan', 4, 75000),
33 ('Grace Dell', 5, 125000),
34 ('Nancy Johnson', 3, 85000),
35 ('John Doe', 2, 45000),
36 ('Lily Bush', 3, 55000);
The merit’s percentages are stored in the merits table therefore, you have to use the UPDATE INNER
JOIN statement to adjust the salary of employees in the employees table based on
the percentage stored in the merits table.
The link between the employees and merit tables is the performance field. See the following query:
1 UPDATE employees
2 INNER JOIN
3 merits ON employees.performance = merits.performance
4 SET
5 salary = salary + salary * percentage;
How the query works.
We specify only the employees table after UPDATE clause because we want to update data in
the employees table only.
For each row in the employees table, the query checks the value in the performance column against the
value in the performance column in the merits table. If it finds a match, it gets the percentage in
the merits table and updates the salary column in the employees table.
Because we omit the WHERE clause in the UPDATE statement, all the records in the employees table get
updated.
Because these employees are new hires so their performance data is not available or NULL .
To increase the salary for new hires, you cannot use the UPDATE INNER JOIN statement because their
performance data is not available in the merit table. This is why the UPDATE LEFT JOIN comes to
the rescue.
The UPDATE LEFT JOIN statement basically updates a row in a table when it does not have a
corresponding row in another table.
For example, you can increase the salary for a new hire by 1.5% using the following statement:
1 UPDATE employees
2 LEFT JOIN
3 merits ON employees.performance = merits.performance
4 SET
5 salary = salary + salary * 0.015
6 WHERE
7 merits.percentage IS NULL;
In this tutorial, we have shown you how to use the MySQL UPDATE JOIN with the INNER JOIN and LEFT
JOIN clauses to perform the cross-table update.
MySQL DELETE
Summary: in this tutorial, you will learn how to use the MySQL DELETE statement to delete data from a
single table.
In this statement:
Notice that the WHERE clause is optional. If you omit the WHERE clause, the DELETE statement will delete all
rows in the table.
Besides deleting data from a table, the DELETE statement returns the number of rows deleted.
To delete data from multiple tables using a single DELETE statement, you use the DELETE JOIN
statement which we will cover in the next tutorial.
To delete all rows in a table without the need of knowing how many rows deleted, you should use
the TRUNCATE TABLE statement to get a better performance.
For a table that has a foreign key constraint, when you delete rows from the parent table, the rows in the
child table will be deleted automatically by using the ON DELETE CASCADE option.
We will use the employees table in the sample database for the demonstration.
Note that once you delete data, it is gone. Therefore, you should backup your database before performing
the DELETE statements in the next section.
Suppose you want to delete employees whose officeNumber is 4, you use the DELETE statement with
the WHERE clause as the following query:
To delete all rows from the employees table, you use the DELETE statement without the WHERE clause as
follows:
Note that the order of rows in a table is unspecified, therefore, when you use the LIMIT clause, you
should always use the ORDER BY clause.
For example, the following statement sorts customers by customer’s names alphabetically and deletes the
first 10 customers:
Similarly, the following DELETE statement selects customers in France , sorts them by credit limit in
ascending order, and deletes the first 5 customers:
In this tutorial, you have learned how to use the MySQL DELETE statement to delete data from a table.
MySQL ON DELETE CASCADE: Deleting Data From
Multiple Related Tables
Summary: in this tutorial, you will learn how to use MySQL ON DELETE CASCADE referential action for
a foreign key to delete data from multiple related tables.
In the previous tutorial, you learned how to delete data from multiple related tables using a
single DELETE statement. However, MySQL provides a more effective way called ON DELETE
CASCADE referential action for a foreign key that allows you to delete data from child tables automatically
when you delete the data from the parent table.
Suppose we have two tables: buildings and rooms . In this database model, each building has one or
more rooms. However, each room belongs to one only one building. A room would not exist without a
building.
The relationship between the buildings and rooms tables is one-to-many (1:N) as illustrated in the
following database diagram:
When we delete a row from the buildings table, we also want to delete the rows in the rooms table that
references to the rows in the buildings table. For example, when we delete a row with building no. 2 in
the buildings table as the following query:
We want the rows in the rooms table that refers to building number 2 will be also removed.
The following are steps that demonstrate how MySQL ON DELETE CASCADE referential action works.
Notice that we add the ON DELETE CASCADE clause at the end of the foreign key constraint definition.
As you can see, all the rows that reference to building_no 2 were deleted.
Notice that ON DELETE CASCADE works only with tables with the storage engines support foreign keys
e.g., InnoDB. Some table types do not support foreign keys such as MyISAM so you should choose
appropriate storage engines for the tables that you plan to use the MySQL ON DELETE
CASCADE referential action.
1 USE information_schema;
2
3 SELECT
4 table_name
5 FROM
6 referential_constraints
7 WHERE
8 constraint_schema = 'database_name'
9 AND referenced_table_name = 'parent_table'
10 AND delete_rule = 'CASCADE'
For example, to find tables that associated with the buildings table with the CASCADE deletion rule in
the classicmodels database, you use the following query:
1 USE information_schema;
2
3 SELECT
4 table_name
5 FROM
6 referential_constraints
7 WHERE
8 constraint_schema = 'classicmodels'
9 AND referenced_table_name = 'buildings'
10 AND delete_rule = 'CASCADE'
In this tutorial, we have shown you step by step how to use the MySQL ON DELETE CASCADE referential
action for a foreign key to delete data automatically from the child tables when you delete data from the
parent table.
In the previous tutorial, you learned how to delete rows of multiple tables by using:
This tutorial introduces to you a more flexible way to delete data from multiple tables using INNER
JOIN or LEFT JOIN clause with the DELETE statement.
For example, to delete rows from both T1 and T2 tables that meet a specified condition, you use the
following statement:
1 DELETE T1, T2
2 FROM T1
3 INNER JOIN T2 ON T1.key = T2.key
4 WHERE condition;
Notice that you put table names T1 and T2 between the DELETE and FROM keywords. If you omit T1 table,
the DELETE statement only deletes rows in T2 table. Similarly, if you omit T2 table, the DELETE statement
will delete only rows in T1 table.
The expression T1.key = T2.key specifies the condition for matching rows between T1 and T2 tables
that will be deleted.
The condition in the WHERE clause determine rows in the T1 and T2 that will be deleted.
Suppose, we have two tables t1 and t2 with the following structures and data:
1 2 row(s) affected
We can also use the LEFT JOIN clause in the DELETE statement to delete rows in a table (left table) that
does not have matching rows in another table (right table).
The following syntax illustrates how to use DELETE statement with LEFT JOIN clause to delete rows
from T1 table that does not have corresponding rows in the T2 table:
1 DELETE T1
2
FROM T1
3
LEFT JOIN
4
T2 ON T1.key = T2.key
5
WHERE
6
T2.key IS NULL;
Note that we only put T1 table after the DELETE keyword, not both T1 and T2 tables like we did with
the INNER JOIN clause.
Each customer has zero or more orders. However, each order belongs to one and only one customer.
We can use DELETE statement with LEFT JOIN clause to clean up our customers master data. The
following statement removes customers who have not placed any order:
1 DELETE customers
2 FROM customers
3 LEFT JOIN
4 orders ON customers.customerNumber = orders.customerNumber
5 WHERE
6 orderNumber IS NULL;
We can verify the delete by finding whether customers who do not have any order exists using the
following query:
1 SELECT
2 c.customerNumber,
3 c.customerName,
4 orderNumber
5 FROM
6 customers c
7 LEFT JOIN
8 orders o ON c.customerNumber = o.customerNumber
9 WHERE
10 orderNumber IS NULL;
In this tutorial, you have learned how to use the MySQL DELETE JOIN statement to delete data from two
or more tables.
MySQL REPLACE
Summary: in this tutorial, you will learn how to use the MySQL REPLACE statement to insert or update
data in database tables.
If the new row already does not exist, the MySQL REPLACE statement inserts a new row.
If the new row already exist, the REPLACE statement deletes the old row first and then inserts a new
row. In some cases, the REPLACE statement updates the existing row only.
To determine whether the new row already exists in the table, MySQL uses PRIMARY KEY or UNIQUE
KEY index. If the table does not have one of these indexes, the REPLACE statement is equivalent to
the INSERT statement.
To use the MySQL REPLACE statement, you need to have at least both INSERT and DELETE privileges.
Notice that there is a REPLACE string function which is not the REPLACE statement covered in this
tutorial.
We query data from the cities table to verify the insert operation.
1 SELECT
2 *
3 FROM
4 cities;
Then, suppose we want to update the population of the New York city to 1008256. We can use
the UPDATE statement as follows:
1 UPDATE cities
2 SET
3 population = 1008256
4 WHERE
5 id = 1;
We query the data from the cities table again to verify the update.
1 SELECT
2 *
3 FROM
4 cities;
Finally, query the data of the cities table again to verify the replacement.
1 SELECT
2 *
3 FROM
4 cities;
The name column is NULL now. You may expect that the value of the name column remains intact.
However, the REPLACE statement does not behave this way. In this case, the REPLACE statement works
as follows:
1. The REPLACE statement first inserts the new row into the cities table with the information provided
by the column list. The insertion fails because the row with id 2 already exists in the cities table,
therefore, MySQL raises a duplicate-key error.
2. The REPLACE statement then updates the row that has the key specified in the value of the id
column. In the normal process, it would delete the old row with conflict id first and then inserts a new
row.
We know that the REPLACE statement did not delete the old row and inserted the new row because the
value of the id column is 2 instead of 4.
For example, if you want to insert a new row into the cities table, you use the following query:
Notice that the default values of the columns that do not appear in the REPLACE statement will be inserted
into the corresponding columns. In case the column that has the NOT NULL attribute and does not have a
default value, and you don’t specify the value in the REPLACE statement, MySQL will raise an error. This is
a difference between the REPLACE and INSERT statements.
For example, in the following statement, we specify only the value for the name column, not
the population column. MySQL raises an error message. Because the population column does not
accept a NULL value and we did not specify a default value for it when we defined the cities table.
For example, if you want to update the population of the Phoenix city to 1768980 , you use
the REPLACE statement as follows:
Unlike the UPDATE statement, if you don’t specify the value for the column in the SET clause,
the REPLACE statement will use the default value of that column.
1 SELECT
2 *
3 FROM
4 cities;
Suppose, you want to copy the city with id value 1, you use the REPLACE INTO SELECT statement as the
following query:
If you develop an application that supports not only MySQL database but also other relational
database management systems (RDBMS), you should avoid using the REPLACE statement because
other RDBMS may not support it. Instead, you can use the combination of
the DELETE and INSERT statements within a transaction.
If you are using the REPLACE statement in the table that has triggers and the deletion of duplicate-
key error occurs, the triggers will be fired in the following sequence: BEFORE INSERT BEFORE
DELETE , AFTER DELETE , AFTER INSERT in case the REPLACE statement deletes current row and
inserts the new row. In case the REPLACE statement updates the current row, the BEFORE
UPDATE and AFTER UPDATE triggers are fired.
In this tutorial, you’ve learned different forms of REPLACE statement to insert or update data in tables.
The textual protocol has serious performance implication. To resolve this problem, MySQL added a new
feature called prepared statement since version 4.1.
The prepared statement takes advantage of client/server binary protocol. It passes query that contains
placeholders (?) to the MySQL server as the following example:
1 SELECT *
2 FROM products
3 WHERE productCode = ?;
When MySQL executes this query with different productcode values, it does not have to parse the query
fully. As a result, this helps MySQL execute the query faster, especially when MySQL executes the query
multiple times. Because the prepared statement uses placeholders (?), this helps avoid many variants of
SQL injection hence make your application more secure.
First, we used the PREPARE statement to prepare a statement for execution. We used
the SELECT statement to query product data from the products table based on a specified product
code. We used a question mark (?) as a placeholder for the product code.
Next, we declared a product code variable @pc and set it values to S10_1678 .
Then, we used the EXECUTE statement to execute the prepared statement with the product code
variable @pc .
MySQL table locking – learn how to use MySQL locking for cooperating table access between
sessions.
MySQL Transaction
Summary: in this tutorial, you will learn about MySQL transaction and how to use MySQL COMMIT
statement and MySQL ROLLBACK statement to manage transactions in MySQL.
Query the latest sales order number from the orders table, and use the next sales order number as
the new sales order number.
Insert a new sales order into the orders table for a given customer.
Get data from both table orders and orderdetails tables to confirm the changes
Now imagine what would happen to your data if one or more steps above fail because of database failure
such as table lock security? If the step of adding order items into orderdetails table failed, you would
have an empty sales order in your system without knowing it. Your data may not be integrity and the effort
you have to spend to fix it is tremendous.
How do you solve this problem? That’s why the transaction processing comes to the rescue. MySQL
transaction enables you to execute a set of MySQL operations to ensure that the database never contains
the result of partial operations. In a set of operations, if one of them fails, the rollback occurs to restore the
database. If no error occurred, the entire set of statements is committed to the database.
Notice that there are some SQL statements, mostly data definition statements, that you cannot use within
a transaction:
To write the changes into the database within a transaction, you use the COMMIT statement. It is important
to note that MySQL automatically commits the changes to the database by default.
To force MySQL not to commit changes automatically, you use the following statement:
1 SET autocommit = 0;
Let’s take a look an example of using MySQL transaction to add new sales order into our sample
database above and add the transaction processing steps:
In this tutorial, you’ve learned how to use MySQL transaction statements that include START
TRANSACTION COMMI, and ROLLBACK to manage transactions in MySQL to protect data integrity.
MySQL allows a client session to acquire a table lock explicitly for preventing other sessions from
accessing the table during a specific period. A client session can acquire or release table locks only for
itself. It cannot acquire or release table locks for other sessions.
Before going into detail, we will create a sample database named sampledb that includes a simple table
named tbl to practice the table locking statements.
You put the name of the table after the LOCK TABLES keywords and followed by a lock type. MySQL
provides two lock types: READ and WRITE . We will go into detail of each lock type in the next section.
1 UNLOCK TABLES;
A READ lock for a table can be acquired by multiple sessions at the same time. In addition, other
sessions can read data from the table without acquiring the lock.
The session that holds the READ lock can only read data from the table, but not write. In addition,
other sessions cannot write data into the table until the READ lock is released. The write operations
from another session will be put into the waiting states until the READ lock is released.
If the session is terminated normally or abnormally, MySQL will release all the locks implicitly. This
is also relevant for the WRITE lock.
Let’s take a look at how the READ lock works in the following scenario.
First, connect to the sampledb database. To find out the current connection id, you use
the CONNECTION_ID() function as follows:
1 SELECT CONNECTION_ID();
After that, to acquire a lock, you use the LOCK TABLE statement.
Finally, in the same session, if you try to insert a new row into the tbl table, you will get an error
message.
1 Error Code: 1099. Table 'tbl' was locked with a READ lock and can't be updated.
So the once READ lock is acquired, you cannot write data into the table within the same session. Let’s
check the READ lock from a different session.
1 SELECT CONNECTION_ID();
Next, insert a new row into the tbl table from the second session.
You can see the detailed information from the SHOW PROCESSLIST statement.
1 SHOW PROCESSLIST;
After that, go back to the first session and release the lock by using the UNLOCK TABLES statement.
After you release the READ lock from the first session, the INSERT operation in the second session
executed.
Finally, check it the data of the tbl table to see if the INSERT operation from the second session really
executed.
Only session that holds the lock of a table can read and write data from the table.
Other sessions cannot read and write from the table until the WRITE lock is released.
Let’s go into detail to see how the WRITE lock works.
It is fine.
After that, from the second session, try to write and read data:
MySQL puts those operations into a waiting state. You can check it using the SHOW
PROCESSLIST statement.
1 SHOW PROCESSLIST
1 UNLOCK TABLES;
You will see all pending operations from the second session executed.
In this tutorial, we have shown you how to lock and unlock tables for READ and WRITE to cooperate table
access between sessions.
Managing database in MySQL – you will learn various statements to manage MySQL databases
including creating a new database, removing an existing database, selecting a database, and listing
all databases.
Understanding MySQL Table Types – it is essential to understand the features of each table type so
that you can use them effectively to maximize the performance of your databases.
CREATE TABLE – show you how to create new tables in a database using CREATE
TABLE statement.
MySQL sequence – show you how to use a sequence to generate unique numbers automatically for
the primary key column of a table.
ALTER TABLE – learn how to use the ALTER TABLE statement to change existing table’s structure.
Renaming table – show you how to rename a table using RENAME TABLE statement.
Removing a column from a table – show you how to use the ALTER TABLE DROP COLUMN statement
to remove one or more columns from a table.
Adding a new column to a table – show you how to add one or more columns to an existing table
using ALTER TABLE ADD COLUMN statement.
DROP TABLE – show you how to remove existing tables using DROP TABLE statement.
MySQL temporary table – discuss MySQL temporary table and show you how to manage temporary
tables.
TRUNCATE TABLE – show you how to use the TRUNCATE TABLE statement to delete all data in a
table fast.
To create a database in MySQL, you use the CREATE DATABASE statement as follows:
Followed by the CREATE DATABASE statement is database name that you want to create. It is
recommended that the database name should be as meaningful and descriptive as possible.
The IF NOT EXISTS is an optional clause of the statement. The IF NOT EXISTS clause prevents
you from an error of creating a new database that already exists in the database server. You cannot
have 2 databases with the same name in a MySQL database server.
For example, to create classicmodels database, you can execute the CREATE DATABASE statement as
follows:
After executing this statement, MySQL returns a message to notify that the new database has been
created successfully or not.
Displaying Databases
The SHOW DATABASES statement displays all databases in the MySQL database server. You can use
the SHOW DATABASES statement to check the database that you’ve created or to see all the databases on
the database server before you create a new database, for example:
1 SHOW DATABASES;
We have three databases in the MySQL database server. The information_schema and mysql are the
default databases that are available when we install MySQL, and the classicmodels is the new
database that we have created.
1 USE database_name;
You can select the classicmodels sample database using the USE statement as follows:
1 USE classicmodels;
From now all operations such as querying data, create new tables or calling stored procedures which you
perform, will take effects on the current database i.e., classicmodels .
Removing Databases
Removing database means you delete the database physically. All the data and associated objects inside
the database are permanently deleted and this cannot be undone. Therefore, it is very important to
execute this query with extra cautions.
Followed the DROP DATABASE is the database name that you want to remove. Similar to the CREATE
DATABASE statement, the IF EXISTS is an optional part of the statement to prevent you from removing a
database that does not exist in the database server.
If you want to practice with the DROP DATABASE statement, you can create a new database, make sure
that it is created, and remove it. Let’s look at the following queries:
1. First, we created a database named temp_database using the CREATE DATABASE statement.
In this tutorial, you’ve learned various statements to manage databases in MySQL including creating a
new database, removing an existing database, selecting a database to work with, and displaying all
databases in a MySQL database server.
Understanding MySQL Table Types, or Storage
Engines
Summary: in this tutorial, you will learn various MySQL table types or storage engines. It is essential to
understand the features of each table type in MySQL so that you can use them effectively to maximize the
performance of your databases.
MyISAM
InnoDB
MERGE
MEMORY (HEAP)
ARCHIVE
CSV
FEDERATED
Each storage engine has its own advantages and disadvantages. It is crucial to understand each storage
engine features and choose the most appropriate one for your tables to maximize the performance of the
database. In the following sections, we will discuss each storage engine and its features so that you can
decide which one to use.
MyISAM
MyISAM extends the former ISAM storage engine. The MyISAM tables are optimized for compression and
speed. MyISAM tables are also portable between platforms and operating systems.
The size of MyISAM table can be up to 256TB, which is huge. In addition, MyISAM tables can be
compressed into read-only tables to save spaces. At startup, MySQL checks MyISAM tables for corruption
and even repairs them in a case of errors. The MyISAM tables are not transaction-safe.
Before MySQL version 5.5, MyISAM is the default storage engine when you create a table without
specifying the storage engine explicitly. From version 5.5, MySQL uses InnoDB as the default storage
engine.
InnoDB
The InnoDB tables fully support ACID-compliant and transactions. They are also optimal for performance.
InnoDB table supports foreign keys, commit, rollback, roll-forward operations. The size of an InnoDB table
can be up to 64TB.
Like MyISAM, the InnoDB tables are portable between different platforms and operating systems. MySQL
also checks and repairs InnoDB tables, if necessary, at startup.
MERGE
A MERGE table is a virtual table that combines multiple MyISAM tables that have a similar structure into
one table. The MERGE storage engine is also known as the MRG_MyISAM engine. The MERGE table
does not have its own indexes; it uses indexes of the component tables instead.
Using MERGE table, you can speed up performance when joining multiple tables. MySQL only allows you
to perform SELECT, DELETE, UPDATE and INSERT operations on the MERGE tables. If you use DROP
TABLE statement on a MERGE table, only MERGE specification is removed. The underlying tables will
not be affected.
Memory
The memory tables are stored in memory and use hash indexes so that they are faster than MyISAM
tables. The lifetime of the data of the memory tables depends on the uptime of the database server. The
memory storage engine is formerly known as HEAP.
Archive
The archive storage engine allows you to store a large number of records, which for archiving purpose,
into a compressed format to save disk space. The archive storage engine compresses a record when it is
inserted and decompress it using the zlib library as it is read.
The archive tables only allow INSERT and SELECT statements. The ARCHIVE tables do not support
indexes, so it is required a full table scanning for reading rows.
CSV
The CSV storage engine stores data in comma-separated values (CSV) file format. A CSV table brings a
convenient way to migrate data into non-SQL applications such as spreadsheet software.
CSV table does not support NULL data type. In addition, the read operation requires a full table scan.
FEDERATED
The FEDERATED storage engine allows you to manage data from a remote MySQL server without using
cluster or replication technology. The local federated table stores no data. When you query data from a
local federated table, the data is pulled automatically from the remote federated tables.
In this tutorial, you have learned various storage engines or table types available in MySQL.
The following illustrates the syntax of the CREATE TABLE statement in the simple form:
First, you specify the name of the table that you want to create after the CREATE TABLE clause. The
table name must be unique within a database. The IF NOT EXISTS is an optional part of the
statement that allows you to check if the table that you are creating already exists in the database. If
this is the case, MySQL will ignore the whole statement and will not create any new table. It is highly
recommended that you use IF NOT EXISTS in every CREATE TABLE statement for preventing from
an error of creating a new table that already exists.
Second, you specify a list of columns for the table in the column_list section. Columns are
separated by a comma (,). We will show you how to define columns in more detail in the next
section.
Third, you need to specify the storage engine for the table in the engine clause. You can use any
storage engine such as InnoDB, MyISAM, HEAP, EXAMPLE, CSV, ARCHIVE, MERGE
FEDERATED or NDBCLUSTER. If you don’t declare the storage engine explicitly, MySQL will use
InnoDB by default.
InnoDB became the default storage engine since MySQL version 5.5. The InnoDB table type brings many
benefits of relational database management system such as ACID transaction, referential integrity, and
crash recovery. In previous versions, MySQL used MyISAM as the default storage engine.
To define a column for the table in the CREATE TABLE statement, you use the following syntax:
The column_name specifies the name of the column. Each column has a specific data type and the
size e.g., VARCHAR(255)
The NOT NULL or NULL indicates that the column accepts NULL value or not.
The DEFAULT value is used to specify the default value of the column.
The AUTO_INCREMENT indicates that the value of the column is increased automatically whenever a
new row is inserted into the table. Each table has one and only one AUTO_INCREMENT column.
If you want to set particular columns of the table as the primary key, you use the following syntax:
In this tutorial, you have learned how to use MySQL CREATE TABLE statement to create a new table in a
database.
MySQL Sequence
Summary: in this tutorial, we will show you how to use MySQL sequence to automatically generate
unique numbers for ID columns of tables.
To create a sequence in MySQL automatically, you set the AUTO_INCREMENT attribute to a column, which
typically is a primary key column.
The following rules are applied when you use the AUTO_INCREMENT attribute:
Each table has only one AUTO_INCREMENT column whose data type is typically the integer.
The AUTO_INCREMENT column must be indexed, which means it can be either PRIMARY
KEY or UNIQUE index.
The AUTO_INCREMENT column must have a NOT NULL constraint. When you set
the AUTO_INCREMENT attribute to a column, MySQL automatically add the NOT NULL constraint to
the column implicitly.
The starting value of an AUTO_INCREMENT column is 1 and it is increased by 1 when you insert
a NULL value into the column or when you omit its value in the INSERT statement.
To obtain the last generated sequence number, you use the LAST_INSERT_ID() function. We often
use the last insert ID for the subsequent statements e.g., insert data into the tables. The last
generated sequence is unique across sessions. In other words, if another connection generates a
sequence number, from your connection you can obtain it by using the LAST_INSERT_ID() function.
If you insert a new row into a table and specify a value for the sequence column, MySQL will insert
the sequence number if the sequence number does not exist in the column or issue an error if it
already exists. If you insert a new value that is greater than the next sequence number, MySQL will
use the new value as the starting sequence number and generate a unique sequence number
greater than the current one for the next usage. This creates gaps in the sequence.
If you use the UPDATE statement to update values in the AUTO_INCREMENT column to a value that
already exists, MySQL will issue a duplicate-key error if the column has a unique index. If you
update an AUTO_INCREMENT column to a value that is greater than the existing values in the column,
MySQL will use the next number of the last insert sequence number for the next row. For example, if
the last insert sequence number is 3, you update it to 10, the sequence number for the new row is 4.
If you use the DELETE statement to delete the last inserted row, MySQL may or may not reuse the
deleted sequence number depending on the storage engine of the table. A MyISAM table does not
reuse the deleted sequence numbers if you delete a row e.g., the last insert id in the table is 10, if
you remove it, MySQL still generates the next sequence number which is 11 for the new row.
Similar to MyISAM tables, InnoDB tables do not reuse sequence number when rows are deleted.
Once you set the AUTO_INCREMENT attribute for a column, you can reset the auto increment value in
various ways e.g., by using the ALTER TABLE statement.
Let’s take a look at some example to get a better understanding of the MySQL sequence.
Because the storage engine of the employees table is InnoDB, it does not reuse the deleted sequence
number. The new row has emp_no 3.
1 UPDATE employees
2 SET first_name = 'Joe',
3 emp_no = 1
4 WHERE emp_no = 3;
MySQL issued an error of duplicate entry for the primary key. Let’s fix it.
1 UPDATE employees
2 SET first_name = 'Joe',
3 emp_no = 10
4 WHERE emp_no = 3;
Sixth, insert a new employee after updating the sequence number to 10:
The next sequence number of the last insert is number 4, therefore, MySQL uses number 4 for the new
row instead of 11.
In this tutorial, you have learned how to use MySQL sequence to generate unique numbers for a primary
key column by assigning the AUTO_INCREMENT attribute to the column.
Using MySQL ALTER TABLE To Change Table
Structure
Summary: in this tutorial, you will learn about the MySQL ALTER TABLE statement that changes
existing table structure such as adding or removing columns, changing column attributes, etc.
First, you specify the table name, which you want to change, after the ALTER TABLE clause.
Second, you list a set of actions that you want to apply to the table. An action can be anything such
as adding a new column, adding primary key, renaming table, etc. The ALTER TABLE statement
allows you to apply multiple actions in a single ALTER TABLE statement, each action is separated by
a comma (,).
Let’s create a new table for practicing the ALTER TABLE statement.
We’re going to create a new table named tasks in the sample database. The following is the script for
creating the tasks table.
You can verify the change by inserting some rows to the tasks table.
And you can query data to see if the value of the task_id column is increased by 1 each time you
insert a new row:
1 SELECT
2 task_id, description
3 FROM
4 tasks;
Using MySQL ALTER TABLE statement to add a new column into a table
Because of the new business requirements, you need to add a new column called complete to store the
percentage of completion for each task in the tasks table. In this case, you can use the ALTER TABLE to
add a new column to the tasks table as follows:
The following statement renames the tasks table to the work_items table:
In this tutorial, you’ve learned how to use the MySQL ALTER TABLE statement to change existing table
structure and to rename the table.
To change one or more tables, we use the RENAME TABLE statement as follows:
The old table ( old_table_name ) must exist, and the new table ( new_table_name ) must not. If the new
table new_table_name does exist, the statement will fail.
In addition to the tables, we can use the RENAME TABLE statement to rename views.
Before we execute the RENAME TABLE statement, we must ensure that there is no active transactions
or locked tables.
Note that you cannot use the RENAME TABLE statement to rename a temporary table, but you can use
the ALTER TABLE statement to rename a temporary table.
In terms of security, any existing privileges that we granted to the old table must be manually migrated to
the new table.
Before renaming a table, you should evaluate the impact thoroughly. For example, you should investigate
which applications are using the table. If the name of the table changes, so the application code that
refers to the table name needs to be changed as well. In addition, you must manually adjust other
database objects such as views, stored procedures, triggers, foreign key constraints, etc., that reference
to the table. We will discuss this in more detail in the following examples.
Second, we insert sample data into both employees and departments tables:
1 SELECT
2 department_id, dept_name
3 FROM
4 departments;
1 SELECT
2 id, first_name, last_name, department_id
3 FROM
4 employees;
Renaming a table referenced by a view
If the table that you are going to rename is referenced by a view, the view will become invalid if you
rename the table, and you have to adjust the view manually.
The views use the inner join clause to join departments and employees tables.
The following SELECT statement returns all data from the v_employee_info view.
1 SELECT
2 *
3 FROM
4 v_employee_info;
Now we rename the employees to people table and query data from the v_employee_info view again.
We can use the CHECK TABLE statement to check the status of the v_employee_info view as follows:
We need to manually change the v_employee_info view so that it refers to the people table instead of
the employees table.
Then, create a new stored procedure named get_employee that refers to the employees table.
1 DELIMITER $$
2
3 CREATE PROCEDURE get_employee(IN p_id INT)
4
5 BEGIN
6 SELECT first_name
7 ,last_name
8 ,dept_name
9 FROM employees
10 INNER JOIN departments using (department_id)
11 WHERE id = p_id;
12 END $$
13
14 DELIMITER;
Next, we execute the get_employee table to get the data of the employee with id 1 as follows:
1 CALL get_employee(1);
Finally, we call the get_employee stored procedure to get the information of employee with id 2:
1 CALL get_employee(2);
MySQL returns the following error message:
To fix this, we must manually change the employees table in the stored procedure to people table.
The department_i d column in the employees table is the foreign key that references to
the departments table.
If we rename the departments table, all the foreign keys that point to the departments table will not be
automatically updated. In such cases, we must drop and recreate the foreign keys manually.
We delete a department with id 1, because of the foreign key constraint, all rows in the people table
should be also deleted. However, we renamed the departments table to the depts table without
updating the foreign key manually, MySQL returns an error as illustrated below:
Error Code: 1451. Cannot delete or update a parent row: a foreign key constraint fails (`hr`.`people`, CONSTRAINT
1
`people_ibfk_1` FOREIGN KEY (`department_id`) REFERENCES `depts` (`department_id`))
Renaming multiple tables
We can also use the RENAME TABLE statement to rename multiple tables at a time. See the following
statement:
The following statement renames the people and depts tables to employees and departments tables:
Note the RENAME TABLE statement is not atomic. It means that if any errors occurred, MySQL does a
rollback all renamed tables to their old names.
The ALTER TABLE statement can rename a temporary table while the RENAME TABLE statement cannot.
1 Error Code: 1017. Can't find file: '.\hr\lastnames.frm' (errno: 2 - No such file or directory)
Third, we use the ALTER TABLE statement to rename the lastnames table.
In this tutorial, we have shown you how to rename tables using MySQL RENAME TABLE and ALTER
TABLE statements.
First, you specify the table that contains the column you want to remove after the ALTER
TABLE clause.
Second, you put the name of the column following the DROP COLUMN clause.
Note that the keyword COLUMN is optional so you can use the shorter statement as follows:
To remove multiple columns from a table at the same time, you use the following syntax:
There are some important points you should remember before you remove a column from a table:
Removing a column from a table makes all database objects such as stored
procedures, views, triggers, etc., that depend on the column invalid. For example, you may have a
stored procedure that references to a column. When you remove the column, the stored procedure
will become invalid. To fix it, you have to manually change the stored procedure’s code manually.
The code from other applications that depends on the removed column must be also changed,
which takes time and efforts.
Removing a column from a large table can impact the performance of the database.
Third, to remove both created_at and updated_at columns at the same time, you use the following
statement:
Third, make the category_id column as a foreign key that references to the id column of
the categories table.
1 Error Code: 1553. Cannot drop index 'fk_cat': needed in a foreign key constraint
To avoid this error, you must remove the foreign key constraint before dropping the column.
In this tutorial, we have shown you how to use MySQL DROP COLUMN statement to remove one or more
columns from a table.
First, you specify the table name after the ALTER TABLE clause.
Second, you put the new column and its definition after the ADD COLUMN clause. Note
that COLUMN keyword is optional so you can omit it.
Third, MySQL allows you to add the new column as the first column of the table by specifying
the FIRST keyword. It also allows you to add the new column after an existing column using
the AFTER existing_column clause. If you don’t explicitly specify the position of the new column,
MySQL will add it as the last column.
To add two or more columns to a table at the same time, you use the following syntax:
Let’s take a look some examples of adding a new column to an existing table.
Second, we add a new column named phone to the vendors table. Because we specify the position of
the phone column explicitly after the name column, MySQL will obey this.
Third, we add a new column named vendor_group to the vendors table. At this time, we don’t specify
the new column’s position so MySQL adds the vendor_group column as the last column of
the vendors table.
We can query the data of the vendors table to see the changes.
1 SELECT
2 id, name, phone,vendor_group
3 FROM
4 vendors;
Fourth, add two more columns email and hourly_rate to the vendors table at the same time.
Note that both email and hourly_rate columns are assigned to NOT NULL values However,
the vendors table already has data. In such cases, MySQL will use default values for those new columns.
1 SELECT
2 id, name, phone, vendor_group, email, hourly_rate
3 FROM
4 vendors;
The email column is populated with blank values, not the NULL values. And the hourly_rate column is
populated with 0.00 values.
If you accidentally add a column that already exists in the table, MySQL will issue an error. For example, if
you execute the following statement:
For the table with a few columns, it is easy to see which columns are already there. However, with a big
table with hundred of columns, it is more difficult.
In some situations, you want to check whether a column already exists in a table before adding it.
However, there is no statement like ADD COLUMN IF NOT EXISTS available. Fortunately, you can get this
information from the columns table of the information_schema database as the following query:
1 SELECT
2 IF(count(*) = 1, 'Exist','Not Exist') AS result
3 FROM
4 information_schema.columns
5 WHERE
6 table_schema = 'classicmodels'
7 AND table_name = 'vendors'
8 AND column_name = 'phone';
In the WHERE clause, we passed three arguments: table schema or database, table name, and column
name. We used IF function to return whether the column exists or not.
In this tutorial, you have learned how to add one or more columns to a table using MySQL ADD COLUMN
statement.
The DROP TABLE statement removes a table and its data permanently from the database. In MySQL, you
can also remove multiple tables using a single DROP TABLE statement, each table is separated by a
comma (,).
The TEMPORARY flag allows you to remove temporary tables only. It is very convenient to ensure that you
do not accidentally remove non-temporary tables.
The IF EXISTS addition helps you prevent from removing non-existent tables. When you use IF
EXISTS addition, MySQL generates a NOTE, which can be retrieved by using the SHOW
WARNING statement. It is important to note that the DROP TABLE statement removes all existing tables and
issues an error message or a NOTE when you have a non-existent table in the list.
As mentioned above, the DROP TABLE statement only removes table and its data. However, it does not
remove specific user privileges associated with the table. Therefore if a table with the same name is re-
created after that, the existing privileges will apply to the new table, which may pose a security risk.
The RESTRICT and CASCADE flags are reserved for the future versions of MySQL.
Last but not least, you must have DROP privileges for the table that you want to remove.
1 SHOW WARNINGS;
However, there are some workarounds. We will discuss one of them here for your reference.
We’ve created four tables named test1 , test2 , test3 and test4 with the same table structure.
Suppose you want to remove all test* tables at a time, you can follow the steps below:
First, you declare two variables that accept database schema and a pattern that you want to the tables to
match:
Basically, the query instructs MySQL to go to the information_schema table , which contains data on
all tables in all databases, and to concatenate all tables in the database @schema ( classicmodels ) that
matches the pattern @pattern ( test% ) with the prefix DROP TABLE . The GROUP_CONCAT
functioncreates a comma-separated list of tables.
After that, we can execute the statement using prepared statement in MySQL as follows:
For more information on MySQL prepared statement, check it out the MySQL prepared statementtutorial.
So if you want to drop multiple tables that have a specific pattern in a database, you just use the script
above to save time. All you need to do is replacing the pattern and the database
schema in @pattern and @schema variables. If you often have to deal with this task, you can always
develop a stored procedure based on the script and reuse this stored procedure.
In this tutorial, we’ve shown you how to use the DROP TABLE statement to remove existing tables in a
particular database. We also discussed about a workaround that allows you to use the DROP
TABLE statement to remove tables based on pattern matching.
A temporary table is created by using CREATE TEMPORARY TABLE statement. Notice that
the TEMPORARY keyword is added between CREATE and TABLE keywords.
MySQL removes the temporary table automatically when the session ends or the connection is
terminated. Of course, you can use the DROP TABLE statement to remove a temporary table
explicitly when you are no longer use it.
A temporary table is only available and accessible to the client that creates it. Different clients can
create temporary tables with the same name without causing errors because only the client that
creates the temporary table can see it. However, in the same session, two temporary tables cannot
share the same name.
A temporary table can have the same name as a normal table in a database. For example, if you
create a temporary table named employees in the sample database, the existing employees table
becomes inaccessible. Every query you issue against the employees table is now referring to the
temporary employees table. When you drop the employees temporary table, the
permanent employees table is available and accessible again.
Even though a temporary table can have the same name as a permanent table, it is not recommended.
Because this may lead to a confusion and potentially cause an unexpected data loss.
For example, in case the connection to the database server is lost and you reconnect to the server
automatically, you cannot differentiate between the temporary table and the permanent one. Then, you
may issue a DROP TABLE statement to remove the permanent table instead of the temporary table, which
is not expected.
For example, the following statement creates a temporary table that stores the top 10 customers by
revenue:
Now, you can query data from the top10customers temporary table like querying from a permanent
table:
The DROP TEMPORARY TABLE statement removes a temporary table only, not a permanent table. It helps
you avoid the mistake of removing a permanent table when you name your temporary table the same as
the name of the permanent table
For example, to remove the top10customers temporary table, you use the following statement:
Notice that if you try to remove a permanent table with the DROP TEMPORARY TABLE statement, you will
get an error message saying that the table you are trying drop is unknown.
If you develop an application that uses a connection pooling or persistent connections, it is not guaranteed
that the temporary tables are removed automatically when your application is terminated.
Because the database connection that the application used may be still open and placed in a connection
pool for other clients to use. Therefore, it is a good practice to always remove the temporary tables
whenever you are no longer use them.
In this tutorial, you have learned about the MySQL temporary tables and how to manage temporary tables
such as creating and removing a new temporary table.
MySQL TRUNCATE TABLE
Summary: in this tutorial, you will learn how to use the MySQL TRUNCATE TABLE statement to delete
all data in a table.
However, in some cases, the MySQL TRUNCATE TABLE statement is more efficient than
the DELETE statement.
You specify the table name, which you want to remove all data, after the TRUNCATE TABLE clause.
The TABLE keyword is optional. However, you should use it to distinguish between the TRUNCATE
TABLE statement and the TRUNCATE function.
If you are using InnoDB tables, MySQL will check if there are any foreign key constraints available in the
tables before deleting data. The following are cases:
If the table has any foreign key constraints, the TRUNCATE TABLE statement deletes rows one by
one. If the foreign key constraint has DELETE CASCADE action, the corresponding rows in the child
tables are also deleted.
If the foreign key constraint does not specify the DELETE CASCADE action, the TRUNCATE
TABLE deletes rows one by one, and it will stop and issue an error when it encounters a row that is
referenced by a row in a child table.
If the table does not have any foreign key constraint, the TRUNCATE TABLE statement drops the
table and recreates a new empty one with the same structure, which is faster and more efficient
than using the DELETE statement especially for big tables.
If you are using other storage engines, the TRUNCATE TABLE statement just drops and recreates a new
table.
Notice that the TRUNCATE TABLE statement resets auto increment value to zero if the table has
an AUTO_INCREMENT column.
In addition, the TRUNCATE TABLE statement does not use the DELETE statement, therefore, the DELETE
triggers associated with the table will not be invoked.
Next, populate data for the books table by using the following stored procedure
1 DELIMITER $$
2
3 CREATE PROCEDURE load_book_data(IN num int(4))
4 BEGIN
5 DECLARE counter int(4) default 0;
6 DECLARE book_title varchar(255) default '';
7
8 WHILE counter < num DO
9 SET title = concat('Book title #',counter);
10 SET counter = counter + 1;
11
12 INSERT INTO books
13 Values(book_title);
14 END WHILE;
15 END$$
16
17 DELIMITER ;
Then, load 10,000 rows into the books table. It will take a while.
1 CALL load_book_data(10000);
1 SELECT *
2 FROM books;
Finally, use the TRUNCATE TABLE statement to see how fast it performs in comparison with
the DELETE statement.
In this tutorial, we have shown you how to use the MySQL TRUNCATE TABLE statement to delete all
data from tables efficiently, especially for large tables.
Section 12. MySQL indexes
Managing MySQL database indexes – learn how to work with MySQL indexes and how to take
advantages of indexes to speed up the data retrieval.
UNIQUE index – show you how to use the UNIQUE index to enforce the uniqueness of value in one
or more columns.
A database index, or just index, helps speed up the retrieval of data from tables. When you query data
from a table, first MySQL checks if the indexes exist, then MySQL uses the indexes to select exact
physical corresponding rows of the table instead of scanning the whole table.
A database index is similar to an index of a book. If you want to find a topic, you look up in the index first,
and then you open the page that has the topic without scanning the whole book.
It is highly recommended that you create indices on columns of a table from which you often query the
data. Notice that all primary key columns are in the primary index of the table automatically.
If index helps speed up the querying data, why don’t we use indexes for all columns? If you create an
index for every column, MySQL has to build and maintain the index table. Whenever a change is made to
the rows of the table, MySQL has to rebuild the index, which takes time as well as decreases the
performance of the database server.
In order to create indexes, you use the CREATE INDEX statement. The following illustrates the syntax of
the CREATE INDEX statement:
First, you specify the index based on the table type or storage engine:
For the UNIQUE index, MySQL creates a constraint that all values in the index must be unique.
Duplicate NULL values are allowed in all storage engines except for BDB.
The FULLTEXT index is supported only by MyISAM storage engine and only accepted on a column
whose has data type is CHAR , VARCHAR or TEXT.
The SPATIAL index supports spatial column and is available on MyISAM storage engine. In
addition, the column value must not be NULL.
Then, you name the index and its type after the USING keyword. The name of the index could
be BTREEHASH or RTREE.Y ou must follow the allowed indices based on the storage engine of the table.
Here are the storage engines of the table with the corresponding allowed index types:
InnoDB BTREE
NDB HASH
Third, you declare table name and a list columns that you want to add to the index.
Removing Indexes
Besides creating an index, you can also remove index by using the DROP INDEX statement. Interestingly,
the DROP INDEX statement is also mapped to ALTER TABLE statement. The following is the syntax of
removing the index:
For example, if you want to drop index officeCode of the employees table, which we have created
above, you can execute the following query:
In this tutorial, you’ve learned about indexes and how to manage MySQL index including creating and
removing indexes.
Using MySQL UNIQUE Index To Prevent Duplicates
Summary: in this tutorial, you will learn how to use the MySQL UNIQUE index to prevent duplicate values
in one or more column in a table.
However, each table has one and only one primary key. If you want to have a more than one column or a
set of columns with unique values, you cannot use the primary key constraint.
Luckily, MySQL provides another kind of index called UNIQUE index that allows you to enforce the
uniqueness of values in one or more columns. Unlike the PRIMARY KEY index, you can have more than
one UNIQUE index per table.
To create a UNIQUE index, you use the CREATE UNIQUE INDEX statement as follows:
Another way to enforce the uniqueness of value in a one or more columns is to use the unique constraint.
When you create a unique constraint, MySQL creates a UNIQUE index behind the scenes.
The following statement illustrates how to create a unique constraint when you create a table.
You can also use the UNIQUE INDEX instead of the UNIQUE KEY. They are referred to the same thing.
If you want to add a unique constraint to an existing table, you can use the ALTER TABLE statement as
follows:
Another important point is that the UNIQUE constraint does not apply to NULL values except for the
BDB storage engine.
To enforce this rule, you create a unique constraint in the CREATE TABLE statement as follows
If you use the SHOW INDEXES statement, you will see that MySQL created a UNIQUE index for email
column.
Now if you try to insert a row whose email is [email protected] , you will get an error
message.
Suppose you want not only email is unique but also the combination of first_name, last_name, and phone
are also unique. In this case, you use the CREATE INDEX statement to create a UNIQUE index for those
columns as follows:
1 CREATE UNIQUE INDEX idx_name_phone
2 ON contacts(first_name,last_name,phone);
Adding the following row into the contacts table causes an error because the combination of the
first_name, last_name, and phone already exists.
In this tutorial, you have learned how to use the MySQL UNIQUE index to prevent duplicate values in the
database.
INT – show you how to use integer data type. We also show you how to use ZEROFILL and display
width attributes of the integer column.
DECIMAL – show you how to use DECIMAL data type to store exact values in decimal format.
BIT – introduce you BIT data type and how to store bit values in MySQL.
BOOLEAN – explain to you how MySQL handles Boolean values by using TINYINT(1) internally.
CHAR – guide to CHAR data type for storing the fixed-length string.
TEXT – show you how to store text data using TEXT data type.
DATE – introduce you to the DATE data type and show you some date functions to handle the date
data effectively.
TIME – walk you through the features of TIME data type and show you how to use some useful
temporal functions to handle time data.
DATETIME – introduce you to the DATETIME data type and some useful functions to
manipulate DATETIME values.
TIMESTAMP – introduce you to TIMESTAMP and its features called automatic initialization and
automatic update that allows you to define auto-initialized and auto-updated columns for a table.
JSON – show you how to use JSON data type to store JSON documents.
ENUM – learn how to use ENUM data type correctly to store enumeration values.
A database table contains multiple columns with specific data types such as numeric or string. MySQL
provides more data types other than just numeric or string. Each data type in MySQL can be determined
by the following characteristics:
The following table illustrates the MySQL date and time data types:
In this tutorial, you have learned various MySQL data types that help you determine which data type you
should use for columns when you create tables.
MySQL supports all standard SQL integer types INTEGER or INT and SMALLINT . In addition, MySQL
provides TINYINT MEDIUMINT , and BIGINT as extensions to the standard SQL.
MySQL INT data type can be signed and unsigned. The following table illustrates the characteristics of
each integer type including storage in bytes, minimum value, and maximum value.
When you insert a NULL value or 0 into the INT AUTO_INCREMENT column, the value of the column is set
to the next sequence value. Notice that the sequence value starts with 1.
When you insert a value, which is not NULL or zero, into the AUTO_INCREMENT column, the column
accepts the value. In addition, the sequence is reset to next value of the inserted value.
Let’s take a look at an example of a table that uses an integer column with the AUTO_INCREMENT
attributes.
First, create a new table named items with an integer column as the primary key using the following
statement:
you can use either INT or INTEGER in the CREATE TABLE statement above because they are
interchangeable. Whenever you insert a new row into the items table, the value of the item_id column is
increased by 1.
Next, the following INSERT statement inserts three rows into the items table.
Then, query data from the items table using the following SELECT statement:
1 SELECT
2 *
3 FROM
4 items;
After that, insert a new row whose value of the item_id column is specified explicitly.
Because the current value of the item_id column is 10, the sequence is reset to 11. If you insert a new
row, the AUTO_INCREMENT column will use 11 as the next value.
Finally, query the data of the items table again to see the result.
1 SELECT
2 *
3 FROM
4 items;
Note that since MySQL 5.1, the AUTO_INCREMENT column only accepts positive values. Negative values
are not supported for the AUTO_INCREMENT column.
1 SELECT
2 v1, v2, v3
3 FROM
4 zerofill_tests;
The v1 column has a display width 2 including ZEROFILL. Its value is 1 therefore, you see 01 in the
output. MySQL replaces the first space by 0.
The v2 column has a display with 3 including ZEROFILL . Its value is 6 therefore, you see 00 as the
leading zeros.
The v3 column has the display width 5 with ZEROFILL , while its value is 9, therefore MySQL pads 0000 at
the beginning of the number in the output.
Note that if you use ZEROFILL attribute for an integer column, MySQL will automatically add
an UNSIGNED attribute to the column.
In this tutorial, we have shown you how to use MySQL INT data type in the table and also introduced you
to the display width and ZEROFILL attributes of an integer column.
MySQL DECIMAL Data Type
Summary: in this tutorial, we will introduce you to the MySQL DECIMAL data type and how to use it
effectively in your database table.
To define a column whose data type is DECIMAL you use the following syntax:
1 column_name DECIMAL(P,D);
P is the precision that represents the number of significant digits. The range of P is 1 to 65.
D is the scale that that represents the number of digits after the decimal point. The range of D is 0
and 30. MySQL requires that D is less than or equal to (<=) P.
The DECIMAL(P,D) means that the column can store up to P digits with D decimals. The actual range of
the decimal column depends on the precision and scale.
Besides the DECIMAL keyword, you can also use DEC , FIXED , or NUMERIC because they are synonyms
for DECIMAL .
Like the INT data type, the DECIMAL type also has UNSIGNED and ZEROFILL attributes. If we use
the UNSIGNED attribute, the column with DECIMAL UNSIGNED will not accept negative values.
In case we use ZEROFILL , MySQL will pad the display value by 0 up to display width specified by the
column definition. In addition, if we use ZERO FILL for the DECIMAL column, MySQL will add
the UNSIGNED attribute to the column automatically.
The following example defines amount column with DECIMAL data type.
1 amount DECIMAL(6,2);
In this example, the amount column can store 6 digits with 2 decimal places; therefore, the range of the
amount column is from 9999.99 to -9999.99.
1 column_name DECIMAL(P);
1 column_name DECIMAL;
For each part, it takes 4 bytes to store each multiple of 9 digits. The storage required for leftover digits is
illustrated in the following table:
For example, DECIMAL(19,9) has 9 digits for the fractional part and 19-9 = 10 digits for integer part. The
fractional part requires 4 bytes. The integer part requires 4 bytes for the first 9 digits, for 1 leftover digit, it
requires 1 more byte. In total, the DECIMAL(19,9) column requires 9 bytes.
1 amount DECIMAL(19,2);
However, if you want to comply with Generally Accepted Accounting Principles (GAAP) rules, the
monetary column must have at least 4 decimal places to make sure that the rounding value does not
exceed $0.01. In this case, you should define the column with 4 decimal places as follows:
1 amount DECIMAL(19,4);
MySQL DECIMAL data type example
First, create a new table named materials with three columns: id, description, and cost.
1 SELECT
2 *
3 FROM
4 materials;
1 SELECT
2 *
3 FROM
4 materials;
As you see, we have many zeros padded in the output values.
In this tutorial, we have shown gave you detailed information on MySQL DECIMAL data type and shown
you how to apply it to the columns that store exact numeric data such as financial data.
The default value of m is 1 if you omit it. So the following statements are the same:
1 column_name BIT(1);
and
1 column_name BIT;
To specify a bit value literal, you use b'val' or 0bval notation, which val is a binary value that contains
only 0 and 1.
1 b01
2 B11
However, the leading 0b is case-sensitive, therefore, you cannot use 0B . The following is an invalid bit
literal value:
1 0B'1000'
By default the character set of a bit-value literal is the binary string as follows:
The values in days column indicate the working day or day off i.e., 1: working day and 0: day off.
Suppose the Saturday and Friday of the first week of 2017 are not the working days, you can insert a
rowinto the working_calendar table as follows:
1 SELECT
2 y, w , days
3 FROM
4 working_calendar;
As you see, the bit value in the days column is converted into an integer. To represent it as bit values,
you use the BIN function:
1 SELECT
2 y, w , bin(days)
3 FROM
4 working_calendar;
If you insert a value to a BIT(m) column that is less than m bits long, MySQL will pad zeros on the left of
the bit value.
Suppose the first day of the second week is off, you can insert 01111100 into the days column.
However, the 111100 value will also work because MySQL will pad one zero on the left.
1 INSERT INTO working_calendar(y,w,days)
2 VALUES(2017,2,B'111100');
1 SELECT
2 y, w , bin(days)
3 FROM
4 working_calendar;
As you can see, MySQL removed the leading zeros prior returning the result. To display it correctly, you
can use the LPAD function:
1 SELECT
2 y, w , lpad(bin(days),7,'0')
3 FROM
4 working_calendar;
In this tutorial, you have learned how to use the MySQL BIT type to store bit values.
In MySQL, zero is considered as false, and non-zero value is considered as true. To use Boolean literals,
you use the constants TRUE and FALSE that evaluate to 1 and 0 respectively. See the following example:
Even though we specified the completed column as BOOLEAN , when we show the table definition, it
is TINYINT(1) as follows:
1 DESCRIBE tasks;
1 SELECT
2 id, title, completed
3 FROM
4 tasks;
It is working fine.
If you want to output the result as true and false , you can use the IF function as follows:
1 SELECT
2 id,
3 title,
4 IF(completed, 'true', 'false') completed
5 FROM
6 tasks;
1 SELECT
2 id, title, completed
3 FROM
4 tasks
5 WHERE
6 completed = TRUE;
As you see, it only returned the task with completed value 1. To fix it, you must use IS operator:
1 SELECT
2 id, title, completed
3 FROM
4 tasks
5 WHERE
6 completed IS TRUE;
In this example, we used the IS operator to test a value against a Boolean value.
To get the pending tasks, you use IS FALSE or IS NOT TRUE as follows:
1 SELECT
2 id, title, completed
3 FROM
4 tasks
5 WHERE
6 completed IS NOT TRUE
In this tutorial, you have learned how to use the MySQL BOOLEAN data type, which is the synonym
of TINYINT(1) , and how to manipulate Boolean values.
If the data that you want to store is a fixed size, you should use the CHAR data type. You’ll get a better
performance in comparison with VARCHAR in this case.
The length of the CHAR data type can be any value from 0 to 255. When you store a CHAR value, MySQL
pads its value with spaces to the length that you declared.
When you query the CHAR value, MySQL removes the trailing spaces.
Note that MySQL will not remove the trailing spaces if you enable
the PAD_CHAR_TO_FULL_LENGTHSQL mode.
The status column has the CHAR data type. It can hold up to 3 characters.
Now, we insert 2 rows into the mysql_char_test table.
We use the length function to get the length of each CHAR value.
1 SELECT
2 status, LENGTH(status)
3 FROM
4 mysql_char_test;
The following statement inserts a CHAR value with the leading and trailing spaces.
However, when we retrieve the value, MySQL removes the trailing space.
1 SELECT
2 status, LENGTH(status)
3 FROM
4 mysql_char_test;
Comparing MySQL CHAR values
When storing or comparing the CHAR values, MySQL uses the character set collation assigned to the
column.
MySQL does not consider trailing spaces when comparing CHAR values using the comparison operator
such as =, <>, >, <, etc.
Notice that the LIKE operator does consider the trailing spaces when you do pattern matching
with CHAR values.
In the previous example, we stored the value Y with both leading and trailing spaces. However, when we
execute the following query:
1 SELECT
2 *
3 FROM
4 mysql_char_test
5 WHERE
6 status = 'Y';
MySQL returns no row because it does not consider the trailing space. To match with the ‘ Y ‘, we need to
remove the trailing space as follows:
1 SELECT
2 *
3 FROM
4 mysql_char_test
5 WHERE
6 status = ' Y';
First, create a unique index for the status column of the mysql_char_test table.
In this tutorial, we have introduced you to the MySQL CHAR data type and its features. Now, you should
have a good understanding of the CHAR data type to apply it in your database design.
The maximum length, however, is subject to maximum row size (65,535 bytes) and the character setused.
It means that the total length of all columns should be less than 65,535 bytes.
We will create a new table that has two columns s1 and s2 with the length of 32765(+2 for length prefix)
and 32766 (+2).Note that 32765+2+32766+2=65535, which is the maximum row size.
The statement created the table successfully. However, if we increase the length of the s1 column by 1.
Error Code: 1118. Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes
1
storage overhead, check the manual. You have to change some columns to TEXT or BLOBs 0.000 sec
As you can see, the row size is too large and the statement failed.
If you insert a string whose length is greater than the length of a VARCHAR column, MySQL will issue an
error. Consider the following example:
1 Error Code: 1406. Data too long for column 'title' at row 1 0.000 sec
1 SELECT
2 id, title, length(title)
3 FROM
4 items;
However, MySQL will truncate the trailing spaces when inserting a VARCHAR value that contains trailing
spaces which cause the column length exceeded. In addition, MySQL issues a warning. Let’s see the
following example:
This statement inserts a string whose length is 4 into the title column. MySQL still inserts the string,
however, it truncates the trailing space before inserting the value.
1 1 row(s) affected, 1 warning(s): 1265 Data truncated for column 'title' at row 1
1 SELECT
2 title, LENGTH(title)
3 FROM
4 items;
In this tutorial, you have learned how to use MySQL VARCHAR data type to store variable strings in the
database.
The TEXT is useful for storing long-form text strings that can take from 1 byte to 4 GB. We often find
the TEXT data type for storing article body in news sites, product description in e-commerce sites.
Different from CHAR and VARCHAR , you don’t have to specify a storage length when you use a TEXT type
for a column. In addition, MySQL does not remove or pad spaces when retrieve or insert text data
like CHAR and VARCHAR .
Note that the TEXT data is not stored in the database server’s memory, therefore, whenever you
query TEXT data, MySQL has to read from it from the disk, which is much slower in comparison
with CHAR and VARCHAR .
MySQL provides four TEXT types: TINYTEXT , TEXT , MEDIUMTEXT , and LONGTEXT .
The following shows the size of each TEXT type with the assumption that we are using a character set that
take 1 byte to store a character
You should use TINYTEXT for column that require less than 255 characters, has inconsistent length, and
does not require sorting such as excerpt of a blog post, summary of an article, etc.
See the following example:
In this example, we created a new table named articles that has summary column with the data type
is TINYTEXT .
The TEXT can hold the body of an article. Consider the following example:
In this example, we added the body column with TEXT data type to the articles table using the ALTER
TABLE statement.
The MEDIUMTEXT is useful for storing quite large text data like text of a book, white papers, etc. For
example:
1 CREATE TABLE whitepapers (
2 id INT AUTO_INCREMENT PRIMARY KEY,
3 body MEDIUMTEXT NOT NULL,
4 published_on DATE NOT NULL
5 );
For example, you may prefer to use mm-dd-yyyy format but you can’t. Instead, you follow the standard
date format and use the DATE_FORMAT function to format the date the way you want.
MySQL uses 3 bytes to store a DATE value. The DATE values range from 1000-01-01 to 9999-12-31 . If
you want to store a date value that is out of this range, you need to use a non-temporal data type
like integer e.g., three columns, and each column for the year, month, and day. You also need to
create stored functions to simulate the built-in date functions provided by MySQL, which is not
recommended.
When strict mode is disabled, MySQL converts any invalid date e.g., 2015-02-30 to the zero
date value 0000-00-00 .
First, create a table named people with birth date column with DATE data type.
1 SELECT
2 first_name,
3 last_name,
4 birth_date
5 FROM
6 people;
After that, use the two-digit year format to insert data into the people table.
In the first row, we used 01 (range 00-69) as the year, so MySQL converted it to 2001. In the second row,
we used 80 (range 70-99) as the year, MySQL converted it to 1980.
Finally, we can query data from the people table to check whether data was converted based on the
conversion rules.
1 SELECT
2 first_name,
3 last_name,
4 birth_date
5 FROM
6 people;
MySQL provides many useful date functions that allow you to manipulate date effectively.
To get the current date and time, you use NOW() function.
1 SELECT NOW();
1 +---------------------+
2 | NOW() |
3 +---------------------+
4 | 2017-05-13 07:59:38 |
5 +---------------------+
6 1 row in set (0.02 sec)
To get only date part of a DATETIME value, you use the DATE() function.
1 SELECT DATE(NOW());
1 +-------------+
2 | DATE(NOW()) |
3 +-------------+
4 | 2015-07-13 |
5 +-------------+
6 1 row in set (0.01 sec)
To get the current system date, you use CURDATE() function as follows:
1 SELECT CURDATE();
1 +------------+
2 | CURDATE() |
3 +------------+
4 | 2015-07-13 |
5 +------------+
6 1 row in set (0.02 sec)
To format a date value, you use DATE_FORMAT function. The following statement formats the date
as mm/dd/yyyy using the date format pattern %m/%d/%Y :
1 +------------+
2 | today |
3 +------------+
4 | 07/13/2015 |
5 +------------+
6 1 row in set (0.02 sec)
To calculate the number of days between two date values, you use the DATEDIFF function as follows:
1 +------+
2 | days |
3 +------+
4 | 365 |
5 +------+
6 1 row in set (0.02 sec)
To add a number of days, weeks, months, years, etc., to a date value, you use the DATE_ADD function:
1 SELECT
2 '2015-01-01' start,
3 DATE_ADD('2015-01-01', INTERVAL 1 DAY) 'one day later',
4 DATE_ADD('2015-01-01', INTERVAL 1 WEEK) 'one week later',
5 DATE_ADD('2015-01-01', INTERVAL 1 MONTH) 'one month later',
6 DATE_ADD('2015-01-01', INTERVAL 1 YEAR) 'one year later';
Similarly, you can subtract an interval from a date using the DATE_SUB function:
1 SELECT
2 '2015-01-01' start,
3 DATE_SUB('2015-01-01', INTERVAL 1 DAY) 'one day before',
4 DATE_SUB('2015-01-01', INTERVAL 1 WEEK) 'one week before',
5 DATE_SUB('2015-01-01', INTERVAL 1 MONTH) 'one month before',
6 DATE_SUB('2015-01-01', INTERVAL 1 YEAR) 'one year before';
If you want to get the day, month, quarter, and year of a date value, you can use the corresponding
function DAY , MONTH , QUARTER , and YEAR as follows:
1 +------+-------+---------+------+
2 | day | month | quarter | year |
3 +------+-------+---------+------+
4 | 31 | 12 | 4 | 2000 |
5 +------+-------+---------+------+
6 1 row in set (0.00 sec)
To get the week information week related functions. For example, WEEK function returns the week
number, WEEKDAY function returns the weekday index, and WEEKOFYEAR function returns the calendar
week.
1 SELECT
2 WEEKDAY('2000-12-31') weekday,
3 WEEK('2000-12-31') week,
4 WEEKOFYEAR('2000-12-31') weekofyear;
1 +---------+------+------------+
2 | weekday | week | weekofyear |
3 +---------+------+------------+
4| 6 | 53 | 52 |
5 +---------+------+------------+
6 1 row in set (0.04 sec)
The week function returns the week number with the zero-based index if you don’t pass the second
argument or if you pass 0. If you pass 1, it will return week number with 1-indexed.
1 SELECT
2 WEEKDAY('2000-12-31') weekday,
3 WEEK('2000-12-31',1) week,
4 WEEKOFYEAR('2000-12-31') weekofyear;
1 +---------+------+------------+
2 | weekday | week | weekofyear |
3 +---------+------+------------+
4| 6 | 52 | 52 |
5 +---------+------+------------+
6 1 row in set (0.00 sec)
In this tutorial, you have learned about the MySQL DATE data type and how to use some
useful date functions to manipulate date values.
1 column_name TIME;
For example, the following snippet defines a column named start_at with TIME data type.
1 start_at TIME;
A TIME value ranges from -838:59:59 to 838:59:59 . In addition, a TIME value can have fractional
seconds part that is up to microseconds precision (6 digits). To define a column whose data type
is TIME with a fractional second precision part, you use the following syntax:
1 column_name TIME(N);
1 begin_at TIME(3);
A TIME value takes 3 bytes for storage. In case a TIME value includes fractional second precision, it will
take additional bytes based on the number of digits of the fractional second precision. The following table
illustrates the storage required for fractional second precision.
For example, TIME and TIME(0) takes 3 bytes. TIME(1) and TIME(2) takes 4 bytes (3 +
The data types of the start_at and end_at columns are TIME .
1 SELECT
2 name, start_at, end_at
3 FROM
4 tests;
Notice that we use 'HH:MM:SS' as the literal time value in the INSERT statement. Let’s examine all the
valid time literals that MySQL can recognize.
MySQL allows you to use the 'HHMMSS' format without delimiter ( : ) to represent time value. For
example, '08:30:00' and '10:15:00' can be rewritten as '083000' and '101500' .
However, 108000 is not a valid time value because 80 does not represent the correct minute. In this case,
MySQL will raise an error if you try to insert an invalid time value into a table.
MySQL issued the following error message after executing the above statement.
1 Error Code: 1292. Incorrect time value: '108000' for column 'end_at' at row 1
In addition to the string format, MySQL accepts the HHMMSS as a number that represents a time value.
You can also use SS , MMSS . For example, instead of using '082000' , you can use 082000 as follows:
If you use the delimiter:, you can use 1 digit to represent hours, minutes, or seconds. For
example, 9:5:0 can be used instead of '09:05:00' .
The CURRENT_TIME function returns the current time value as a string ( 'HH:MM:SS' ) or a numeric value
( HHMMSS ) depending on the context where the function is used.
The following statements illustrate the CURRENT_TIME function in both string and numeric contexts:
1 SELECT
2 CURRENT_TIME() AS string_now,
3 CURRENT_TIME() + 0 AS numeric_now;
The following statement adds and subtracts 2 hours 30 minutes to and from the current time.
1 SELECT
2 CURRENT_TIME(),
3 ADDTIME(CURRENT_TIME(), 023000),
4 SUBTIME(CURRENT_TIME(), 023000);
In addition, you can use the TIMEDIFF() function to get a difference between two TIME values.
1 SELECT
2 TIMEDIFF(end_at, start_at)
3 FROM
4 tests;
The TIME_FORMAT function is like the DATE_FORMAT function except that the TIME_FORMAT function is
used to format a TIME value only.
See the following example.
1 SELECT
2 name,
3 TIME_FORMAT(start_at, '%h:%i %p') start_at,
4 TIME_FORMAT(end_at, '%h:%i %p') end_at
5 FROM
6 tests;
1 SELECT
2 CURRENT_TIME(),
3 UTC_TIME();
In this tutorial, we have been covered a lot about MySQL TIME data type and some commonly used
temporal functions for manipulating TIME values.
1 YYYY-MM-DD HH:MM:SS
A DATETIME value uses 5 bytes for storage. In addition, a DATETIME value can include a trailing fractional
second up to microseconds with the format YYYY-MM-DD HH:MM:SS[.fraction] e.g., 2015-12-20
10:01:00.999999 . When including the fractional second precision, DATETIME values require more
storage as illustrated in the following table:
Fractional Seconds Precision Storage (Bytes)
0 0
1, 2 1
3, 4 2
5, 6 3
For example, 2015-12-20 10:01:00.999999 requires 8 bytes, 5 bytes for 2015-12-20 10:01:00 and
3 bytes for .999999 while 2015-12-20 10:01:00.9 requires only 6 bytes, 1 byte for the fractional
second precision.
Note that before MySQL 5.6.4, DATETIME values requires 8 bytes storage instead of 5 bytes.
MySQL DATETIME vs. TIMESTAMP
MySQL provides another temporal data type that is similar to the DATETIME called TIMESTAMP .
Both TIMESTAMP and DATETIME require additional bytes for fractional seconds precision.
TIMESTAMP values range from 1970-01-01 00:00:01 UTC to 2038-01-19 03:14:07 UTC . If you want
to store temporal values that are beyond 2038, you should use DATETIME instead of TIMESTAMP .
MySQL stores TIMESTAMP in UTC value. However, MySQL stores the DATETIME value as is without
timezone. Let’s see the following example.
Then, insert the current date and time into both ts and dt columns of the timestamp_n_datetime table,
1 SELECT
2 ts,
3 dt
4 FROM
5 timestamp_n_datetime;
Finally, set the connection’s time zone to +03:00 and query data from the timestamp_n_datetime table
again.
As you can see, the value in the TIMESTAMP column is different. This is because the TIMESTAMP column
stores the date and time value in UTC when we changed the time zone, the value of
the TIMESTAMP column is adjusted according to the new time zone.
It means that if you use the TIMESTAMP data to store date and time values, you should take a serious
consideration when you move your database to a server located in a different time zone.
To query the value of the @dt variable, you use the following SELECT statement:
1 SELECT @dt;
MySQL DATE function
To extract the date portion from a DATETIME value, you use the DATE function as follows:
1 SELECT DATE(@dt);
This function is very useful in case you want to query data based on a date but the data stored in the
column is based on both date and time.
Suppose you want to know which row created on 2015-11-05 , you use the following query:
1 SELECT
2 *
3 FROM
4 test_dt
5 WHERE
6 created_at = '2015-11-05';
It returns no rows.
This is because the created_at column contains not only date but also time. To correct it, you use
the DATE function as follows:
1 SELECT
2 *
3 FROM
4 test_dt
5 WHERE
6 DATE(created_at) = '2015-11-05';
It returns one row as expected. In case the table has many rows, MySQL has to perform a full table scan
to locate the rows that match the condition.
1 SELECT TIME(@dt);
1 SELECT
2 HOUR(@dt),
3 MINUTE(@dt),
4 SECOND(@dt),
5 DAY(@dt),
6 WEEK(@dt),
7 MONTH(@dt),
8 QUARTER(@dt),
9 YEAR(@dt);
First, create a table named datediff_test that has one column whose data type is DATETIME .
Third, use the DATEDIFF function to compare the current date and time with the value in each row of
the datediff_test table.
1 SELECT
2 dt,
3 DATEDIFF(NOW(), dt)
4 FROM
5 datediff_test;
In this tutorial, you have learned about MySQL DATETIME data type and some useful DATETIME functions.
MySQL TIMESTAMP
Summary: in this tutorial, you will learn about MySQL TIMESTAMP and TIMESTAMP column features
such as automatic initialization and updating.
The TIMESTAMP value has a range from '1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07'
UTC .
When you insert a TIMESTAMP value into a table, MySQL converts it from your connection’s time zone to
UTC for storage. When you query a TIMESTAMP value, MySQL converts the UTC value back to your
connection’s time zone. Notice that this conversion does not take place for other temporal data types such
as DATETIME .
By default, the connection time zone is the MySQL database server’s time zone. You can use a different
time zone when you connect to MySQL database server.
When you retrieve a TIMESTAMP value that was inserted by a client in a different time zone, you will get a
value that is not the same as the value stored in the database. As long as you don’t change the time zone,
you can get the same TIMESTAMP value that you stored.
First, created a new table named test_timestamp that has a TIMESTAMP column: t1 ;
Second, set session the time zone to ‘+00:00’ UTC by using the SET time_zone statement.
1 SET time_zone='+00:00';
1 SELECT
2 t1
3 FROM
4 test_timestamp;
Fifth, set the session’s time zone to a different time zone to see what value we get back from the database
server:
As you see, we received a different time value adjusted to the new time zone.
In the categories table, the created_at column is a TIMESTAMP column whose default value is set
to CURRENT_TIMESTAMP .
The following statement inserts a new row into the categories table without specifying the value for
the created_at column:
1 SELECT
2 *
3 FROM
4 categories;
As you can see, MySQL used the timestamp (at the time it inserted the row ) to initialize for
the created_at column.
So a TIMESTAMP column can be automatically initialized to the current timestamp for inserted rows that
specify no value for the column. This feature is called automatic initialization.
We will add a new column named updated_at to the categories table.
The default value of the updated_at column is CURRENT_TIMESTAMP . However, there is a clause ON
UPDATE CURRENT_TIMESTAMP that follows the DEFAULT CURRENT_TIMESTAMP clause. We will find out its
meaning soon.
The following statement inserts a new row into the categories table.
The default value of the created_at column is the timestamp when the row was inserted.
Now, we update the value in the name column of the row with id 2 and query data from
the categories table .
1 UPDATE categories
2 SET
3 name = 'B+'
4 WHERE
5 id = 2;
1 SELECT
2 *
3 FROM
4 categories
5 WHERE
6 id = 2;
Notice that the value in the updated_at column changed to the timestamp at the time the row was
updated.
The ability of a TIMESTAMP column to be automatically updated to the current timestamp when the value in
any other column in the row changed from it current value is called automatic updating.
Note that if you execute the UPDATE statement to update a same value for the name column,
the updated_at column will not be updated.
1 UPDATE categories
2 SET
3 name = 'B+'
4 WHERE
5 id = 2;
For more information on automatic initialized and updating, please check it out the time initialization on
MySQL website.
As of MySQL 5.6.5, the DATETIME columns also have automatic initialization and updating features. In
addition, the DEFAULT_CURRENT_TIMESTAMP and ON UPDATE CURRENT TIMESTAMP can be applied to
multiple columns.
In this tutorial, we have introduced you to MySQL TIMESTAMP data type and shown you how to use
automatic initialization and updating features of TIMESTAMP columns work.
MySQL stores JSON documents in an internal format that allows quick read access to document
elements. The JSON binary format is structured in the way that permits the server to search for values
within the JSON document directly by key or array index, which is very fast.
The storage of a JSON document is approximately the same as the storage
of LONGBLOB or LONGTEXT data.
To define a column whose data type is JSON, you use the following syntax:
Notice that a JSON column cannot have a default value. In addition, a JSON column cannot
be indexeddirectly. Instead, you can create an index on a generated column that contains values
extracted from the JSON column. When you query data from the JSON column, the MySQL optimizer will
look for compatible indexes on virtual columns that match JSON expressions.
Each event in the events table has an id that uniquely identifies the event. An event also has a name
e.g., pageview, purchase, etc., The visitor column is used to store the visitor information.
The properties and browser columns are the JSON columns. They are used to store properties of an
event and specification of the browser that visitors use to browse the website.
To pull values out of the JSON columns, you use the column path operator ( -> ).
1 +----+-----------+
2 | id | browser |
3 +----+-----------+
4 | 1 | "Safari" |
5 | 2 | "Firefox" |
6 | 3 | "Safari" |
7 | 4 | "Firefox" |
8 | 5 | "Firefox" |
9 | 6 | "Chrome" |
10 +----+-----------+
11 6 rows in set (0.00 sec)
Notice that data in the browser column is surrounded by quote marks. To remove the quote marks, you
use the inline path operator ( ->> ) as follows:
1 SELECT id, browser->>'$.name' browser
2 FROM events;
As you can see in the following output, the quote marks were removed:
1 +----+---------+
2 | id | browser |
3 +----+---------+
4 | 1 | Safari |
5 | 2 | Firefox |
6 | 3 | Safari |
7 | 4 | Firefox |
8 | 5 | Firefox |
9 | 6 | Chrome |
10 +----+---------+
11 6 rows in set (0.00 sec)
To get the browser usage, you can use the following statement:
1 +---------+----------------+
2 | browser | count(browser) |
3 +---------+----------------+
4 | Safari | 2|
5 | Firefox | 3|
6 | Chrome | 1|
7 +---------+----------------+
8 3 rows in set (0.02 sec)
To calculate the total revenue by the visitor, you use the following query:
1 +---------+---------+
2 | visitor | revenue |
3 +---------+---------+
4|3 | 200 |
5|4 | 650 |
6 +---------+---------+
7 2 rows in set (0.00 sec)
In this tutorial, you have learned about the MySQL JSON data type and how to use it for storing JSON
documents in the database.
Compact data storage. MySQL ENUM uses numeric indexes (1, 2, 3, …) to represents string values.
In this syntax, you can have more than three enumeration values. However, it is a good practice to keep
the number of enumeration values under 20.
Suppose, we have to store ticket information with the priority: low, medium, and high. To assign
the priority column the ENUM type, you use the following CREATE TABLE statement:
The priority column will accept only three values Low , Medium and High . Behind the scenes, MySQL
maps each enumeration member to a numeric index. In this case, Low , Medium , and High are map to 1, 2
and 3 respectively.
To insert data into an ENUM column, you use the enumeration values in the predefined list. For example,
the following statement inserts a new row into the tickets table.
Besides the enumeration values, you can use the numeric index of the enumeration member for inserting
data into an ENUM column. For instance, the following statement inserts a new ticket with the Low priority:
Because we defined the priority as a NOT NULL column, when you insert a new row without specifying
the value for the priority column, MySQL will use the first enumeration member as the default value.
In the non-strict SQL mode, if you insert an invalid value into an ENUM column, MySQL will use an empty
string '' with the numeric index 0 for inserting. In case the strict SQL mode is enabled, trying to insert an
invalid ENUM value will result in an error.
Note that an ENUM column can accept NULL values if it is defined as a null-able column.
Filtering MySQL ENUM values
1 SELECT
2 *
3 FROM
4 tickets
5 WHERE
6 priority = 'High';
Because the enumeration member ‘High’ is mapped to 3, the following query returns the same result set:
1 SELECT
2 *
3 FROM
4 tickets
5 WHERE
6 priority = 3;
The following query selects the tickets and sorts them by the priority from High to Low :
1 SELECT
2 title, priority
3 FROM
4 tickets
5 ORDER BY priority DESC;
It’s always a good practice to define the enumeration values in the order that you want to sort when you
create the column.
1. Changing enumeration members requires rebuilding the entire table using the ALTER
TABLE statement, which is expensive in terms of resources and time.
Getting the complete enumeration list is complex because you need to access
the information_schema database:
1 SELECT
2 column_type
3 FROM
4 information_schema.COLUMNS
5 WHERE
6 TABLE_NAME = 'tickets'
7 AND COLUMN_NAME = 'priority';
2. Porting to other RDBMS could be an issue because ENUM is not SQL-standard and not many
database system support it.
3. Adding more attributes to the enumeration list is impossible. Suppose you want to add a service
agreement for each priority e.g., High (24h), Medium (1-2 days), Low (1 week), it is not possible
with ENUM . In this case, you need to have a separate table for storing priority list e.g., priorities(id,
name, sort_order, description) and replace the priority field in the tickets table
by priority_id that references to the id field of the priorities table.
4. Comparing to the look-up table ( priorities ), an enumeration list is not reusable. For example, if
you want to create a new table named tasks and want to reuse the priority list, it is not possible.
In this tutorial, we have introduced you to MySQL ENUM data type and how to use it for defining columns
that store enumeration values.
Primary key constraint – guide you how to use primary key constraint to create the primary key for
a table.
Foreign key constraint – introduce you to the foreign key and show you step by step how to create
and drop foreign keys.
UNIQUE constraint – show you how to use UNIQUE constraint to enforce the uniqueness of values
in a column or a group of columns in a table.
CHECK constraint emulation – walk you through various ways to emulate the CHECK constraint in
MySQL.
A column may contain one NOT NULL constraint only, which specifies a rule that the column must not
contain any NULL value.
The title and start_date columns have the NOT NULL constraints explicitly. The id column has
the PRIMARY KEY constraint, therefore, it implicitly includes a NOT NULL constraint.
The end_date column can have NULL values. This is because when we add a new task we may not know
its end date.
It’s a best practice to have the NOT NULL constraint in every column of a table unless you have a good
reason not to do so.
Generally, the NULL value makes your queries more complicated. In such cases, you can use the NOT
NULL constraint and provide a default value for the column. See the following example:
In this example, the default value for quantity column is 0. Because at the time we add a row to
the inventory table, the value of the quantity column should be 0, not NULL .
Now, suppose you want to force users to give estimated end date when creating a new task. To do this,
you need to add the NOT NULL constraint to the end_date column of the tasks table.
First, check the value of end_date table. We use the IS NULL operator to check if the value in a column
is NULL or not:
1 SELECT
2 *
3 FROM
4 tasks
5 WHERE
6 end_date IS NULL;
The query returns one row with the end_date value is NULL .
Second, update the NULL values to non-null values. In this case, we can create a rule that if
the end_date is NULL , we make the end date one week after the start date.
1 UPDATE tasks
2 SET
3 end_date = start_date + 7
4 WHERE
5 end_date IS NULL;
1 SELECT
2 *
3 FROM
4 tasks
Third, add the NOT NULL constraint to the code end_date column. To do it, you use the following ALTER
TABLE statement:
In our case, the old column name and the new column name must be the same except for the column
definition that has the NOT NULL constraint:
1 DESCRIBE tasks;
As you see, the NOT NULL constraint was added to the end_date column.
In this tutorial, you have learned how to define NOT NULL constraint for a column and add the NOT
NULL constraint to an existing column.
A primary key must contain unique values. If the primary key consists of multiple columns, the
combination of values in these columns must be unique.
A primary key column cannot contain NULL values. It means that you have to declare the primary
key column with the NOT NULL attribute. If you don’t, MySQL will force the primary key column
as NOT NULL implicitly.
Because MySQL works faster with integers, the data type of the primary key column should be the integer
e.g., INT, BIGINT. You can choose a smaller integer type: TINYINT , SMALLINT , etc. However, you should
make sure that the range of values of the integer type for the primary key is sufficient for storing all
possible rows that the table may have.
A primary key column often has the AUTO_INCREMENT attribute that generates a unique sequence for the
key automatically. The primary key of the next row is greater than the previous one.
MySQL creates an index named PRIMARY with PRIMARY type for the primary key in a table.
The following example creates users table whose primary key is user_id column:
1 CREATE TABLE users(
2 user_id INT AUTO_INCREMENT PRIMARY KEY,
3 username VARCHAR(40),
4 password VARCHAR(255),
5 email VARCHAR(255)
6 );
You can also specify the PRIMARY KEY at the end of the CREATE TABLE statement as follows:
Besides creating the primary key that consists of user_id and role_id columns, the statement also
created two foreign key constraints.
1 ALTER TABLE t1
2 ADD PRIMARY KEY(id);
A UNIQUE index creates a constraint for a column whose values must be unique. Unlike
the PRIMARY index, MySQL allows NULL values in the UNIQUE index. A table can also have
multiple UNIQUE indexes.
For example, the email and username of a user in the users table must be unique. You can
define UNIQUE indexes for the email and username columns as the following statement:
In this tutorial, you have learned how to create a primary key for a new table or add a primary key for an
existing table.
Let’s take a look at the following database diagram in the sample database.
We have two tables: customers and orders. Each customer has zero or more orders and each order
belongs to only one customer. The relationship between customers table and orders table is one-to-
many, and it is established by a foreign key in the orders table specified by the customerNumber field.
The customerNumber field in the orders table relates to the customerNumber primary key field in
the customers table.
The customers table is called parent table or referenced table, and the orders table is known as child
table or referencing table.
A foreign key can be a column or a set of columns. The columns in the child table often refer to
the primary key columns in the parent table.
A table may have more than one foreign key, and each foreign key in the child table may refer to a
different parent table.
A row in the child table must contain values that exist in the parent table e.g., each order record in
the orders table must have a customerNumber that exists in the customers table. Multiple orders can
refer to the same customer therefore, this relationship is called one (customer) to many (orders), or one-
to-many.
Sometimes, the child and parent tables are the same. The foreign key refers back to the primary key of
the table e.g., the following employees table:
The reportTo column is a foreign key that refers to the employeeNumber column which is the primary
key of the employees table to reflect the reporting structure between employees i.e., each employee
reports to another employee and an employee can have zero or more direct reports. We have a
specific tutorial on the self-join to help you query data against this kind of table.
The reportTo foreign key is also known as recursive or self-referencing foreign key.
Foreign keys enforce referential integrity that helps you maintain the consistency and integrity of the data
automatically. For example, you cannot create an order for a non-existent customer.
In addition, you can set up a cascade on delete action for the customerNumber foreign key so that when
you delete a customer in the customers table, all the orders associated with the customer are also
deleted. This saves you time and efforts of using multiple DELETE statements or a DELETE JOIN
statement.
The same as deletion, you can also define a cascade on update action for the customerNumber foreign
key to perform the cross-table update without using multiple UPDATE statements or an UPDATE JOIN
statement.
In MySQL, the InnoDB storage engine supports foreign keys so that you must create InnoDB tables in
order to use foreign key constraints.
1 CONSTRAINT constraint_name
2 FOREIGN KEY foreign_key_name (columns)
3 REFERENCES parent_table(columns)
4 ON DELETE action
5 ON UPDATE action
Let’s examine the syntax in greater detail:
The CONSTRAINT clause allows you to define constraint name for the foreign key constraint. If you
omit it, MySQL will generate a name automatically.
The FOREIGN KEY clause specifies the columns in the child table that refers to primary key columns
in the parent table. You can put a foreign key name after FOREIGN KEY clause or leave it to let
MySQL create a name for you. Notice that MySQL automatically creates an index with
the foreign_key_name name.
The REFERENCES clause specifies the parent table and its columns to which the columns in the child
table refer. The number of columns in the child table and parent table specified in the FOREIGN
KEY and REFERENCES must be the same.
The ON DELETE clause allows you to define what happens to the records in the child table when the
records in the parent table are deleted. If you omit the ON DELETE clause and delete a record in the
parent table that has records in the child table refer to, MySQL will reject the deletion. In addition,
MySQL also provides you with actions so that you can have other options such as ON DELETE
CASCADE that ask MySQL to delete records in the child table that refers to a record in the parent
table when the record in the parent table is deleted. If you don’t want the related records in the child
table to be deleted, you use the ON DELETE SET NULL action instead. MySQL will set the foreign
key column values in the child table to NULL when the record in the parent table is deleted, with a
condition that the foreign key column in the child table must accept NULL values. Notice that if you
use ON DELETE NO ACTION or ON DELETE RESTRICT action, MySQL will reject the deletion.
The ON UPDATE clause enables you to specify what happens to the rows in the child table when
rows in the parent table are updated. You can omit the ON UPDATE clause to let MySQL reject any
updates to the rows in the child table when the rows in the parent table are updated. The ON
UPDATE CASCADE action allows you to perform a cross-table update, and the ON UPDATE SET
NULL action resets the values in the rows in the child table to NULL values when the rows in the
parent table are updated. The ON UPDATE NO ACTION or UPDATE RESTRICT actions reject any
updates.
1 ALTER table_name
2 ADD CONSTRAINT constraint_name
3 FOREIGN KEY foreign_key_name(columns)
4 REFERENCES parent_table(columns)
5 ON DELETE action
6 ON UPDATE action;
1 USE dbdemo;
2
3 CREATE TABLE vendors(
4 vdr_id int not null auto_increment primary key,
5 vdr_name varchar(255)
6 )ENGINE=InnoDB;
7
8 ALTER TABLE products
9 ADD COLUMN vdr_id int not null AFTER cat_id;
To add a foreign key to the products table, you use the following statement:
Now, the products table has two foreign keys, one refers to the categories table and another refers to
the vendors table.
First, you specify the table name from which you want to remove the foreign key.
Second, you put the constraint name after the DROP FOREIGN KEY clause.
Notice that constraint_name is the name of the constraint specified when you created or added the
foreign key to the table. If you omit it, MySQL generates a constraint name for you.
To obtain the generated constraint name of a table, you use the SHOW CREATE TABLE statement as
follows:
For example, to see the foreign keys of the products table, you use the following statement:
The products table has two foreign key constraints: products_ibfk_1 and products_ibfk_2
You can drop the foreign keys of the products table by using the following statement:
Another example is that, unless you disable the foreign key checks, you cannot drop a table that is
referenced by a foreign key constraint. When you drop a table, any constraints that you defined for the
table are also removed.
1 SET foreign_key_checks = 0;
1 SET foreign_key_checks = 1;
In this tutorial, we have covered a lot about MySQL foreign key. We also introduced you to some very
handy statements that allow you to manage foreign keys effectively in MySQL.
The UNIQUE constraint is either column constraint or table constraint that defines a rule that constrains
values in a column or a group of columns to be unique.
To add the UNIQUE constraint to a column, you use the following syntax:
Or you can define the UNIQUE constraint as the table constraint as follows:
If you insert or update a value that causes a duplicate value in the column_name_1 column, MySQL will
issue an error message and reject the change.
In case you want to enforce unique values across columns, you must define the UNIQUE constraint as the
table constraint and separate the each column by a comma:
MySQL will use the combination of the values in both column_name_1 and column_name_2 columns to
evaluate the uniqueness.
If you want to assign a specific name to a UNIQUE constraint, you use the CONSTRAINT clause as follows:
The following statement creates a new table named suppliers with the two UNIQUE constraints:
The first UNIQUE constraint is applied on the phone column. It means that every supplier must have a
distinct phone number. In other words, no two suppliers have the same phone number.
The second UNIQUE constraint has a name uc_name_address that enforces the uniqueness of values in
the name and address columns. It means suppliers can have the same name or address, but cannot
have the same name and address.
Let’s insert some rows into the suppliers table to test the UNIQUE constraint.
1 1 row(s) affected
We try to insert a different supplier but has the phone number that already exists in the suppliers table.
Let’s change the phone number to a different one and execute the insert statement again.
Now we execute the following INSERT statement to insert a row with the values in the name and address
columns that already exists.
1 Error Code: 1062. Duplicate entry 'XYZ Corporation-400 North 1st Street, San Jose, CA, USA' for key 'name'
As you see, there are two BTREE indexes corresponding to the two UNIQUE constraints created.
To remove a UNIQUE constraint, you use can use DROP INDEX or ALTER TABLE statement as follows:
For example, to remove the uc_name_address constraint on the suppliers table, you the following
statement:
Execute the SHOW INDEX statement again to verify if the uc_name_unique constraint has been removed.
1 SHOW INDEX FROM classicmodels.suppliers;
What if you want to add a UNIQUE constraint to a table that already exists?
For example, to add the uc_name_address UNIQUE constraint back to the suppliers table, you use the
following statement:
Note that the combination of values in the name and address columns must be unique in order to make
the statement execute successfully.
In this tutorial, you have learned how to use the MySQL UNIQUE constraint to enforce the uniqueness of
values in a column or a group of columns in a table.
To follow this tutorial, you need to have a good understanding of triggers, views, and stored procedures.
SQL allows you to apply multiple CHECK constraints to a column or a CHECK constraint across multiple
columns. For example, to make sure that the price is always greater or equal cost, you use the CHECK
constraint as follows:
Once the CHECK constraints are in place, whenever you insert or update a value that causes the Boolean
expression evaluates to false, the check constraint is violated and the database system rejects the
change.
Unfortunately, MySQL does not support CHECK constraint. Actually, MySQL accepts the CHECK clause
in the CREATE TABLE statement but it ignores it silently.
Second, create a stored procedure to check the values in the cost and price columns.
1 DELIMITER $$
2
3 CREATE PROCEDURE `check_parts`(IN cost DECIMAL(10,2), IN price DECIMAL(10,2))
4 BEGIN
5 IF cost < 0 THEN
6 SIGNAL SQLSTATE '45000'
7 SET MESSAGE_TEXT = 'check constraint on parts.cost failed';
8 END IF;
9
10 IF price < 0 THEN
11 SIGNAL SQLSTATE '45001'
12 SET MESSAGE_TEXT = 'check constraint on parts.price failed';
13 END IF;
14
15 IF price < cost THEN
16 SIGNAL SQLSTATE '45002'
17 SET MESSAGE_TEXT = 'check constraint on parts.price & parts.cost failed';
18 END IF;
19
20 END$$
21
22 DELIMITER ;
Third, create BEFORE INSERT and BEFORE UPDATE triggers. Inside the triggers, call
the check_parts() stored procedure.
1 -- before insert
2 DELIMITER $$
3 CREATE TRIGGER `parts_before_insert` BEFORE INSERT ON `parts`
4 FOR EACH ROW
5 BEGIN
6 CALL check_parts(new.cost,new.price);
7 END$$
8 DELIMITER ;
9 -- before update
10 DELIMITER $$
11 CREATE TRIGGER `parts_before_update` BEFORE UPDATE ON `parts`
12 FOR EACH ROW
13 BEGIN
14 CALL check_parts(new.cost,new.price);
15 END$$
16 DELIMITER ;
Fourth, insert a new row that satisfies all the following conditions:
cost > 0
And price > 0
And price >= cost
1 INSERT INTO parts(part_no, description,cost,price)
2 VALUES('A-001','Cooler',100,120);
1 1 row(s) affected
The INSERT statement invokes the BEFORE INSERT trigger and accepts the values.
The following INSERT statement fails because it violates the condition: cost > 0.
The following INSERT statement fails because it violates the condition: price > 0.
The following INSERT statement fails because it violates the condition: price > cost.
1 UPDATE parts
2 SET price = 10
3 WHERE part_no = 'A-001';
So by using two triggers: BEFORE INSERT and BEFORE UPDATE , we are able to emulate the CHECK
constraint in MySQL.
First, drop the parts table to remove all the associated triggers and create a new table like
the parts table but have a different name parts_data :
Second, create a view named parts based on the parts_data table. By doing this, we can keep the
code of the applications that use the parts table remain intact. In addition, all the privileges to the
old parts table remain unchanged.
Third, insert a new row into the parts_data table through the parts view:
It is accepted because the new row is valid which can appear in the view.
However, the following statement fails because the new row would not appear in the view.
In this tutorial, we have introduced you to the standard SQL CHECK constraint and two ways to emulate
the CHECK constraint in MySQL.
MySQL collation – discuss MySQL collation and show you how to set character set and collations
for the MySQL server, database, tables, and columns.
Each character set has one or more collations that define a set of rules for comparing characters within
the character set. Check it out the MySQL collation tutorial to learn about the collations in MySQL.
MySQL supports various character sets that allow you to store almost every character in a string. To get
all available character sets in MySQL database server, you use the SHOW CHARACTER SET statement as
follows:
The values in the Maxlen column specify the number of bytes that a character in a character set holds.
Some character sets contain single-byte characters e.g., latin1 , latin2 , cp850 , etc., whereas other
character sets contain multi-byte characters.
MySQL provides the LENGTH function to get a length of a string in bytes, and the CHAR_LENGTH function to
get the length of a string in characters. If a string contains the multi-bytes character, the result of
the LENGTH function is greater than the result of the CHAR_LENGTH() function. See the following example:
The CONVERT function converts a string into a specific character set. In this example, it converts the
character set of the MySQL Character Set string into ucs2 . Because ucs2 character set contains 2-
byte characters, therefore the length of the @str string in bytes is greater than its length in characters.
Notice that some character sets contain multi-byte characters, but their strings may contain only single-
byte characters e.g., utf8 as shown in the following statements:
The CAST function is similar to the CONVERT function. It converts a string to a different character set:
However, if the database stores Unicode strings in the utf8 character set, using the latin1 character
set in the application would not be sufficient. Therefore, the application needs to specify a proper
character set when it connects to MySQL database server.
To configure a character set for a client connection, you can do one of the following ways:
Issue the SET NAME statement after the client connected to the MySQL database server. For
example, to set a Unicode character set utf8 , you use the following statement:
1 SET NAMES 'utf8';
If the application supports the --default-character-set option, you can use it to set the
character set. For example, mysql client tool supports --default-character-set and you can set
it up in the configuration file as follows:
1 [mysql]
2 default-character-set=utf8
Some MySQL connectors allow you to set character set, for example, if you use PHP PDO, you can
set the character set in the data source name as follows:
1 $dsn ="mysql:host=$host;dbname=$db;charset=utf8";
Regardless of which way you use, make sure that the character set used by the application matches with
the character set stored in the MySQL database server.
In this tutorial, you have learned about MySQL character set, how to convert strings between character
sets and how to configure proper character sets for client connections.
MySQL Collation
Summary: in this tutorial, you will learn about MySQL collation and how to set character sets and
collations for the MySQL server, database, table, and column.
MySQL provides you with the SHOW CHARACTER SET statement that allows you to get the default
collations of character sets as follows:
By convention, a collation for a character set begins with the character set name and ends with _ci (case
insensitive) _cs (case sensitive) or _bin (binary).
To get all collations for a given character set, you use the SHOW COLLATION statement as follows:
For example, to get all collations for the latin1 character set, you use the following statement:
As mentioned above, each character set has at a default collation e.g., latin1_swedish_ci is the default
collation for the latin1 character set.
If you specify only a character set at server startup, MySQL will use the default collation of the character
set. If you specify both a character set and a collation explicitly, MySQL will use the character set and
collation for all databases created in the database server.
The following statement sets the utf8 character set and utf8_unicode_cs collation for the server via
command line:
You can override the default settings at database level by using CREATE DATABASE or ALTER
DATABASEstatement as follows:
MySQL uses the character set and collation at the database level for all tables created within the
database.
You can specify the default character set and collation for a table when you create the table by using
the CREATE TABLE statement or when you alter the table’s structure by using the ALTER
TABLE statement.
1 CREATE TABLE table_name(
2)
3 CHARACTER SET character_set_name
4 COLLATE collation_name
You can specify a character set and a collation for the column in the column’s definition of either CREATE
TABLE or ALTER TABLE statement as follows:
These are the rules for setting the character set and collation:
If you specify both a character set and a collation explicitly, the character set and collation are used.
If you specify a character set and omit the collation, the default collation of the character set is used.
If you specify a collation without a character set, the character set associated with the collation is
used.
If you omit both character set and collation, the default character set and collation are used.
Let’s take a look at some examples of setting the character sets and collations.
Because we specify the character set and collation for the mydbdemo database explicitly,
the mydbdemo does not take the default character set and collation at the server level.
Second, we create a new table named t1 in the mydbdemo database:
1 USE mydbdemo;
2 CREATE TABLE t1(
3 c1 char(25)
4 );
We did not specify the character set and collation for the t1 table; MySQL will check the database level to
determine the character set and collation for the t1 table. In this case, the t1 table has utf8 as the
default character set and utf8_unicode_ci as the default collation.
Third, for the t1 table, we change its character set to latin1 and its collation to latin1_german1_ci :
1 ALTER TABLE t1
2 CHARACTER SET latin1
3 COLLATE latin1_german1_ci;
The c1 column in the t1 table has latin1 as the character set and latin1_german1_ci as the collation.
Fourth, let’s change the character set of the c1 column to latin1 :
1 ALTER TABLE t2
2 MODIFY c1 VARCHAR(25)
3 CHARACTER SET latin1;
Now, the c1 column has the latin1 character set, but what about its collation? Is it inheriting
the latin1_german1_ci collation from the table’s collation? No, because the default collation of
the latin1 character set is latin1_swedish_ci , the c1 column has the latin1_swedish_ci collation.
In this tutorial, you have learned about MySQL collation and how to specify character sets and collations
for MySQL server, databases, tables and columns.
Reference
http://dev.mysql.com/doc/refman/5.7/en/charset.html – MySQL character set support
http://collation-charts.org/mysql60/ – MySQL collation charts
MySQL Export Table to CSV – learn various techniques of how to export MySQL table to a CSV file
format.
Import CSV File Into MySQL Table
This tutorial shows you how to use the LOAD DATA INFILE statement to import CSV file into MySQL
table.
The LOAD DATA INFILE statement allows you to read data from a text file and import the file’s data into a
database table very fast.
A database table to which the data from the file will be imported.
A CSV file with data that matches with the number of columns of the table and the type of data in
each column.
The account, which connects to the MySQL database server, has FILE and INSERT privileges.
The following discounts.csv file contains the first line as column headings and other three lines of data.
The following statement imports data from the c:\tmp\discounts.csv file into the discounts table.
The field of the file is terminated by a comma indicated by FIELD TERMINATED BY ',' and enclosed by
double quotation marks specified by ENCLOSED BY '" ‘.
Each line of the CSV file is terminated by a newline character indicated by LINES TERMINATED BY '\n' .
Because the file has the first line that contains the column headings, which should not be imported into the
table, therefore we ignore it by specifying IGNORE 1 ROWS option.
Now, we can check the discounts table to see whether the data is imported.
Suppose the expired date column in the discount_2.csv file is in mm/dd/yyyy format.
When importing data into the discounts table, we have to transform it into MySQL date format by
using str_to_date() function as follows:
When you use the LOCAL option in the LOAD DATA INFILE , the client program reads the file on the client
and sends it to the MySQL server. The file will be uploaded into the database server operating system’s
temporary folder e.g., C:\windows\temp on Windows or /tmp on Linux. This folder is not configurable
or determined by MySQL.
The only difference is the LOCAL option in the statement. If you load a big CSV file, you will see that with
the LOCAL option, it will be a little bit slower to load the file because it takes time to transfer the file to the
database server.
The account that connects to MySQL server doesn’t need to have the FILE privilege to import the file
when you use the LOCAL option.
Importing the file from client to a remote database server using LOAD DATA LOCAL has some security
issues that you should be aware of to avoid potential security risks.
The following are steps that you want to import data into a table:
We have shown you how to import CSV into MySQL table using LOAD DATA LOCAL and using MySQL
Workbench. With these techniques, you can load data from other text file formats such as tab-delimited.
MySQL Export Table to CSV
Summary: in this tutorial, you will learn various techniques of how to export a MySQL table to a CSV file.
The CSV stands for comma separated values. You often use the CSV file format to exchange data
between applications such as Microsoft Excel, Open Office, Google Docs, etc.
It will be useful to have data from MySQL database in CSV file format because you can analyze and
format the data in the way you want.
MySQL provides an easy way to export the query’s result into a CSV file that resides in the database
server.
The MySQL server’s process has the write access to the target folder that contains the target CSV
file.
The target CSV file must not exist.
The following query selects cancelled orders from the orders table:
1 SELECT
2 orderNumber, status, orderDate, requiredDate, comments
3 FROM
4 orders
5 WHERE
6 status = 'Cancelled';
To export this result set into a CSV file, you add some clauses to the query above as follows:
1 SELECT
2 orderNumber, status, orderDate, requiredDate, comments
3 FROM
4 orders
5 WHERE
6 status = 'Cancelled'
7 INTO OUTFILE 'C:/tmp/cancelled_orders.csv'
8 FIELDS ENCLOSED BY '"'
9 TERMINATED BY ';'
10 ESCAPED BY '"'
11 LINES TERMINATED BY '\r\n';
The statement created a CSV file named cancelled_orders.csv in the C:\tmp folder that contains the
result set.
The CSV file contains lines of rows in the result set. Each line is terminated by a sequence of carriage
return and a line feed character specified by the LINES TERMINATED BY '\r\n' clause. Each line
contains values of each column of the row in the result set.
Each value is enclosed by double quotation marks indicated by FIELDS ENCLOSED BY '”' clause. This
prevents the value that may contain a comma (,) will be interpreted as the field separator. When enclosing
the values by the double quotation marks, the commas inside the value are not recognized as the field
separators.
The following commands export the whole orders table into a CSV file with timestamp as a part of the file
name.
First, we constructed a query with current timestamp as a part of the file name.
Second, we prepared the statement for execution by using PREPARE statement FROM command.
You can wrap the command by an event and schedule the event run periodically if needed.
As the query showed, you need to include the column heading of every column.
1 SELECT
2 orderNumber, orderDate, IFNULL(shippedDate, 'N/A')
3 FROM
4 orders INTO OUTFILE 'C:/tmp/orders2.csv'
5 FIELDS ENCLOSED BY '"'
6 TERMINATED BY ';'
7 ESCAPED BY '"' LINES
8 TERMINATED BY '\r\n';
We replaced NULL values in the shippedDate column by the N/A strings. The CSV file
shows N/A instead of NULL values.