Download as pdf or txt
Download as pdf or txt
You are on page 1of 131

MariaDB

Starter

James Moon
Copyright © 2021 James Moon

All rights reserved.

ISBN: 979-85-6812-298-2
Foreword

'The information society' is no longer an unfamiliar term. 'Information' is now the resource
and power of this contemporary society. And this phenomenon will only get more severe in the
future. Thereby, it is no exaggeration to say that operating and managing information is
essential for all tech workers.
In a modern society where computers are developing into devices for processing and
delivering information beyond simple calculators, anyone in the IT field should have a certain
level of knowledge on the database, the essential tool for managing data. Even seemingly not
database-related software developers need to know how to design a DB, make data input and
output in the database, and collaborate with DB managers.

However, should we all study to the level of a professional DB manager? I wish we could,
but regardless of the possibility, that is not efficient. Nevertheless, most database-related books
on the bookshelves explain too much and too deep. Like they're putting spells into us to be DB
experts. That's why I came to write this book.

This book is not for professional DB managers, nor is it for those who have already studied
the database. This book is for those who want to make the first step into the database world
and the software developers who need to learn the basic structure and operating skills of
database within a week or so.
For that reason, this book would not explain deep inside database theory. Instead, you will
set up your database and make data input and output into it by following the book's contents in
order.

I believe this book will help you make the easiest first step into the database world.

In January 2021, James Moon


Table of Contents

1. Understanding of Database And SQL −−−−−−−−−−−−−−− 1

1-1. What Is Database? −−−−−−−−−−−−−−− 1

1-2. What Is SQL? −−−−−−−−−−−−−−− 2

2. Installation of MariaDB −−−−−−−−−−−−−−− 3

3. Access MariaDB Using HeidiSQL −−−−−−−−−−−−−−− 7

4. Fundamental SQL Queries −−−−−−−−−−−−−−− 9


4-1. SHOW DATABASES −−−−−−−−−−−−−−− 9
4-2. CREATE DATABASE −−−−−−−−−−−−−−− 10
4-3. USE −−−−−−−−−−−−−−− 11
4-4. CREATE TABLE −−−−−−−−−−−−−−− 11
4-5. SHOW TABLES −−−−−−−−−−−−−−− 12
4-6. SHOW COLUMNS −−−−−−−−−−−−−−− 13
4-7. PRIMARY KEY −−−−−−−−−−−−−−− 14
4-8. DROP −−−−−−−−−−−−−−− 15
4-9. SELECT −−−−−−−−−−−−−−− 17
4-10. INSERT INTO −−−−−−−−−−−−−−− 18
4-11. DISTINCT −−−−−−−−−−−−−−− 21
4-12. LIMIT −−−−−−−−−−−−−−− 23
4-13. ORDER BY −−−−−−−−−−−−−−− 25
4-14. Multiple Queries −−−−−−−−−−−−−−− 27
4-15. WHERE −−−−−−−−−−−−−−− 28
4-16. ALTER TABLE −−−−−−−−−−−−−−− 31
4-16-1. ADD −−−−−−−−−−−−−−− 31
4-16-2. DROP COLUMN −−−−−−−−−−−−−−− 32
4-16-3. MODIFY COLUMN −−−−−−−−−−−−−−− 33
4-16-4. CHANGR COLUMN −−−−−−−−−−−−−−− 33
4-17. UPDATE −−−−−−−−−−−−−−− 34
4-18. DELETE −−−−−−−−−−−−−−− 37
4-19. LIKE, NOT LIKE −−−−−−−−−−−−−−− 40

5. Comparison Operators −−−−−−−−−−−−−−− 42

6. Arithmetic Operators −−−−−−−−−−−−−−− 46

7. Functions −−−−−−−−−−−−−−− 48
7-1. String Functions −−−−−−−−−−−−−−− 48
7-2. Numeric Functions −−−−−−−−−−−−−−− 53
7-3. Date Functions −−−−−−−−−−−−−−− 57

8. Advanced SQL Queries −−−−−−−−−−−−−−− 62


8-1. AS −−−−−−−−−−−−−−− 62
8-2. Putting Comments −−−−−−−−−−−−−−− 64
8-2-1. Single-line Comment −−−−−−−−−−−−−−− 64
8-2-2. Multi-line Comment −−−−−−−−−−−−−−− 65
8-3. Sub-Query −−−−−−−−−−−−−−− 67
8-4. Dot Operator −−−−−−−−−−−−−−− 69
8-5. JOIN −−−−−−−−−−−−−−− 71
8-5-1. INNER JOIN −−−−−−−−−−−−−−− 71
8-5-2. LEFT JOIN −−−−−−−−−−−−−−− 74
8-5-3. RIGHT JOIN −−−−−−−−−−−−−−− 76
8-6. UNION −−−−−−−−−−−−−−− 78
8-7. GROUP BY −−−−−−−−−−−−−−− 81
8-8. HAVING −−−−−−−−−−−−−−− 82
8-9. INSERT INTO SELECT : Cloning Table −−−−−−−−−−−−−−− 84
8-10. RENAME TABLE −−−−−−−−−−−−−−− 87
8-11. Temporary Table −−−−−−−−−−−−−−− 88
8-12. CASE −−−−−−−−−−−−−−− 89
8-13. Constraints −−−−−−−−−−−−−−− 92
8-14. FOREIGN KEY −−−−−−−−−−−−−−− 95
8-14-1. Creating Foreign Key −−−−−−−−−−−−−−− 95
8-14-2. Deleting Foreign Key −−−−−−−−−−−−−−− 98
8-14-3. Adding Foreign Key −−−−−−−−−−−−−−− 99
8-15. INDEX −−−−−−−−−−−−−−− 100
8-15-1. Creating Index −−−−−−−−−−−−−−− 100
8-15-2. Deleting Index −−−−−−−−−−−−−−− 101
8-16. Stored Procedure −−−−−−−−−−−−−−− 101
8-16-1. Creating Stored Procedure −−−−−−−−−−−−−−− 101
8-16-2. Deleting Stored Procedure −−−−−−−−−−−−−−− 104

9. User Account Management −−−−−−−−−−−−−−− 105


9-1. Creating New User −−−−−−−−−−−−−−− 105
9-2. Setting Privileges −−−−−−−−−−−−−−− 105
9-3. Revoking Privileges −−−−−−−−−−−−−−− 106
9-4. Deleting User −−−−−−−−−−−−−−− 107

10. Backup and Restore −−−−−−−−−−−−−−− 108


10-1. Full Backup −−−−−−−−−−−−−−− 109
10-2. Partial Backup −−−−−−−−−−−−−−− 109
10-3. Table Backup −−−−−−−−−−−−−−− 110
10-4. Backup without Data −−−−−−−−−−−−−−− 111
10-4-1. Backup All Schema −−−−−−−−−−−−−−− 111
10-4-2. Backup Specific Schema −−−−−−−−−−−−−−− 111
10-5. Scheduled Backup −−−−−−−−−−−−−−− 112
10-6. Restoring Backup −−−−−−−−−−−−−−− 116

11. Data Types in MariaDB −−−−−−−−−−−−−−− 117


11-1. String Data Types −−−−−−−−−−−−−−− 117
11-2. Numeric Data Types −−−−−−−−−−−−−−− 118
11-3. Date and Time Data Types −−−−−−−−−−−−−−− 119
11-4. Binary Data Types −−−−−−−−−−−−−−− 120
11-5. Other Data Types −−−−−−−−−−−−−−− 121
1. Understanding of Database And SQL

1-1. What Is Database?

Database refers to a set of organized data to facilitate access and management, and a
database consists of tables that store data. If you create web services like Instagram or
Facebook, you may need to manage your user information, the contents posted by users, and
the comments on them. All those data will be stored in its corresponding table, and these
tables are managed as a database.

Each table is composed of columns and rows. And the cell which stores data is called a field.
And the set of data stored in a row is called a record: You can think of the form of the
document you can see on Microsoft Excel. If you create a web service, you may make a table
like below to manage your user information.

1
〔 DB Terms 1 〕

As you can see above, a field is a 'container' that holds data. And a record is a bundle that
binds all the data together, which exists across a row.

1-2. What Is SQL?

SQL (stands for Structured Query Language) is the language used to access and manipulate
databases. In addition to MariaDB, there are many different but similar products on the
market, including MySQL, SQL Server, Access, Oracle, Sybase, Informix, Postgres, and so
forth. Although each SQL has its own ups and downs, it mostly follows the rules of ANSI
(American National Standards Institute) and ISO (the International Organization for
Standardization) standards. Furthermore, because MariaDB drives from one of the most
widely used database servers, MySQL, there is no significant difference between MariaDB
and MySQL. Nowadays, SQL is divided into relational and non-relational databases
(NoSQL), and MariaDB, which is covered in this book, belongs to relational database.
Whether relational or non-relational, SQL does the followings:

● New databases can be created and deleted.


● Data can be inserted and deleted in the database.
● New tables can be created and deleted in the database.
● Data can be stored and retrieved from the database.

2
2. Installation of MariaDB

This book describes with the premise that you can access the MariaDB server installed on
your Windows operating system and use HeidiSQL along with it. So before you start this
book, I recommend installing a MariaDB server and HeidiSQL on your computer.

You may download MariaDB installation files from the link below:
http://mariadb.org/

MariaDB is a Relational Database Management System (RDBMS) developed by one of


MySQL's first developers, Ulf Michael Widenius. It is an open-source software distributed
free of charge under the General Public License (GPL) while maintaining maximum
compatibility with MySQL. Unlike MySQL, taken over by Oracle, you can use it even for
commercial purposes.

If downloaded directly from MariaDB.org, HeidiSQL is provided with it.

When you launch the downloaded file, you will see the following window. And the
installation of MariaDB is more straightforward than any other SQL Server.

3
The following window allows you to select the components to install. Make sure that you
choose HeidiSQL here.

The next window will set the password for the superuser, so-called 'root.' You will access
MariaDB using the password set here. The Enable access from remote machines for 'root' in the
middle of the box asks whether to allow access to the database from the distant area as a
superuser. You'd better not allow this unless there is a particular reason. It is because, if a
user is given access from outside with the full authority, it may make your database server
vulnerable to security issues such as hacking. However, it would be good to select Use UTF8 as
default server's charter set at the
bottom. Selecting this will
allow you to use not only
English but also various
languages on your database.

4
You can freely name your database on the next window. TCP ports are channels for
interaction between your computers and the database server. The initial value is '3306', but
you can specify a different port if you want. The range available is from '1024' to '49151.'

Now everything is ready. Press the <install> button on the next window to begin the
installation.

5
Congratulations! The installation is now complete, and you can run your MariaDB server
using HeidiSQL.

6
3. Access MariaDB Using HeidiSQL

Let's run HeidiSQL. The 'Session Manager' window will then appear as follows:

On this window, click the <New> button in the lower-left corner, then select Session in root
folder from the menu following.

7
You can now name the session as you want in the upper left corner of the window: in this
book, I give a name, 'LocalDB.' In the box on the right, type in the password of the root
user you set during the installation. Then click the <Open> button to run HeidiSQL.

〔 DB Terms 2 〕

In SQL, a 'session' is a special path between a user and a SQL server. Each session has its
unique information, which remembers which user has access to which database.

When you start HeidiSQL, you can see the following window. And all SQL queries should
be entered in the 'query window,' and the queries you type in can be executed by clicking the
[▶ ] icon or pressing [F9] on the keyboard.

8
4. Fundamental SQL Queries

The command used in SQL is called 'query.' The data stored in the database is manipulated
and managed through these commands. Now, let's take a look at the most fundamental
queries one by one.

4-1. SHOW DATABASES

A single DB server can have multiple independent databases, and you can see all of them
that exist within the DB server with the statement below:

show databases;

As you can see on the left, you have four


databases after installing MariaDB. Among
these, you may delete the 'test' DB. Other
DBs, however, should not be removed
because they are related to the operation of
the MariaDB server itself.

All the SQL queries are


1. not case-sensitive.
2. to be finished with a semicolon.

In the case of a single or the last query, there will be no problem without adding a
semicolon at the end, which is a bad practice, however. Make it a habit to attach a
semicolon even to the end of a single-line query.

9
〔 DB Terms 3 〕

All commands used in SQL are called 'queries,' but depending on the role each query plays,
they are also reclassified as follows:

1. Main Command = Query


2. A subconcept of a query that gives a condition to return the data value = Keyword
3. A subconcept of a keyword that manipulates data values = Operator
4. When computing data values using parameters = Function

4-2. CREATE DATABASE <name of database>

Now it's time to make your own DB. Type in the following query in your query window.

create database myDB;

Executing the above statement will create a DB named 'mydb.'

Note that 'SHOW DATABASES,' which is used to view all databases, uses the plural form
of database, whereas 'CREATE DATABASE,' a query that creates a new database, uses the
singular form of 'DATABASE.'

10
4-3. USE <name of database>

Since not only can one DB exist within a database server, but numerous DBs can be created
and managed, it is necessary to clarify that the query you input is to which DB. The query
'USE' is employed for this case.

use mydb;

The above statement declares that you will use the DB named 'mydb' from now on. Once
the USE statement is carried out, all subsequent queries will only affect the DB specified by
'USE.' The DB called by 'USE' remains until another DB is called by 'USE' or until the
program(HeidiSQL) itself is terminated.

4-4. CREATE TABLE <name of table>

As I explained earlier, you manage your DB with tables, and the tables store the data within
fields that exist in the tables. To do so, you must declare in advance what kind of data you
will have in each field.

The statement declaring a table will follow the rules as shown below:

CREATE TABLE <name of table>


(
name_of_column data_type (size),
name_of_column data_type (size),
name_of_column data_type (size)
);

The statement declaring the structure of a table will be started with an open parenthesis '('
and ended with a close parenthesis '),' and a semicolon announcing the end of the query
statement will be placed right after the close parenthesis. And you should declare each
column with its name, then sequentially the type and the size of the data ― the declaration of
its size may be omitted in some data types.

11
You may refer to『Chapter. 11』for the information on what types of data MariaDB

allows to use.

Executing the query below will create a table named 'employees.'

create table employees


(
id int auto_increment,
first_name varchar (20),
last_name varchar (20),
department varchar (20),
salary int,
is_admin tinyint (1),
primary key (id)
);

4-5. SHOW TABLES

The query 'SHOW TABLES' will display all the tables in the currently selected DB.

show tables;

You can see the table named 'employees' that we just created by executing the above query.

12
show tables FROM <name of database>;

When using the 'FROM' keyword together, you can immediately see the tables without
specifying the DB by the 'USE' keyword. However, the DB called with the 'FROM' is only
temporary and different from the one declared by 'USE.' In other words, when you use
'FROM,' it will lose effect after the execution of the query, unlike the 'USE' keyword, which
will not lose effect even after the performing of the query.

e.g., show tables from mydb;

4-6. SHOW COLUMNS <from name of database>

show columns from employees;

Executing the statement above shows the information of the columns that exist within the
selected table. However, it only displays the structure of the table, not the actual data stored
in the field.

As you can see above, it only shows the names of fields and data types but does not show
the actual data values. Nevertheless, it is useful when you need to see the property of each
field, so be sure to remember it.

13
〔 DB Terms 4 〕

Field: Name of storage space


Type: Type of data stored
Null: If null value is allowed
Key: The information of primary key, foreign key, etc.
Default: Default value for the field
Extra: Additional information for each column

4-7. PRIMARY KEY

Not all tables should have a primary key, but if you want to make the data easier to access,
it's a good idea to set a primary key. The primary key is like the unique number of each
record stored in the table, and therefore shall meet the following two conditions:

1. must be unique (the same value cannot exist)


2. must not be a null value

For example, in the previously created 'employees' table, the 'id' column can perform the role
of the primary key very well. Because each record is automatically increasing, it neither can
exist as null nor can it have a duplicate value. On the other hand, in the case of 'first_name'
or 'last_name,' it is not appropriate for the primary keys because the same values may exist.

14
The primary key will automatically have a yellow key-shaped icon if you use HeidiSQL.
And a table can have multiple primary keys as needed.

4-8. DROP

'DROP' is the query used to delete a DB or a table that has already been created. When
deleting a database, you use the following syntax:

DROP DATABASE <name of database>

When deleting a table, you use the same syntax. The only difference is to make clear whether
it is a database or a table you want to get rid of.

DROP TABLE <name of table>

drop table employees;


show tables from mydb;

As you can see in the picture above, after executing the 'DROP TABLE' statement, you can
see that the 'employees' table you created earlier has disappeared from the DB. Also,
executing the 'DROP DATABASE' statement shows that the DB named 'myDB' no longer
exists in the list.

15
drop database mydb;
show databases;

When using 'DROP,' you should note that the target is deleted simultaneously as the query
is executed without the reaffirmation procedure usually performed in the deleting process.
Therefore, special attention is needed.

Here, we need to re-create the DB and the table that we deleted to practice other queries.

create database mydb;


use mydb;

create table employees


(
id int auto_increment,
first_name varchar (20),
last_name varchar (20),
department varchar (20),
salary int,
is_admin tinyint (1),
primary key (id)
);

16
4-9. SELECT <name of column> <from name of table>

Compared to 'SHOW COLUMNS,' which shows only the structure of the table and the
information about the data in the fields, the 'SELECT' statement is used to show the actual
data value(s) stored in the selected column(s) of the specified table.

select * from employees;

In the picture above, we only can see the structure of the table, not the data values in it,
because we have never put any data into the table yet. So, now it is time for us to learn how
to make the data input.

'*' used in the above statement is a special character to call all the data at once. Special
characters that function like this will be explained later.

〔 DB Terms 5 〕

'SHOW' is the query that shows information about the structure of a DB or a table, and
'SELECT' is the query that shows the value of the actual data.

17
4-10. INSERT INTO <name of table>

To put data into a table, you will use the following syntax rule:

INSERT INTO <name of table> (field_name_1, field_name_2, field_name_3... field_name_n)


VALUES (data_1, data_2, data_3... data_n);

The field names specified after the table name must match the names of the fields in the
table you defined, and the data values after the 'VALUES' keyword must also be in the same
order as the field names. And for string data, it must be enclosed in quotation marks, but
most other data types do not require them. And you ought to separate each data value that
you want to input with a comma.

insert into employees (first_name, last_name, department, salary, is_admin)


values ('Benjamin', 'Hopper', 'management', 140000, 1);

select * from employees;

The data for the 'id' field was not given in the above statement because 'id' was declared as
having the 'auto_increment' attribute. In other words, 'id' will automatically increase in
value whenever new data comes in. Of course, directly giving a value is also possible.

Then, do we have to enter one record at a time? Of course not. Now, let's see how to insert
multiple data at once.

18
The rule of the syntax is the same in general, but you can insert the desired set of data after
the 'VALUES' keyword, with parentheses like ( ... ), ( ... ), and ( ... ). Each set of data called a
'record' must be separated with a comma, and a semicolon (;) shall be placed after the last
record to indicate the end of the query.

INSERT INTO <name of table> (field_name_1, field_name_2, field_name_3... field_name_n)


VALUES (data_1, data_2, data_3... data_n),
(data_a, data_b, data_c... data_n),
(data_x, data_y, data_z... data_n);

insert into employees (first_name, last_name, department, salary, is_admin)


values ('George', 'Jefferson', 'marketing', 110000, 1),
('Thomas', 'Anthony', 'marketing', 87000, 0),
('Susan', 'Lee', 'sales', 120000, 1),
('Louisa', 'Alcott', 'finance', 120000, 1),
('Dolley', 'Madison ', 'sales', 88000, 0);

select * from employees;

If you have stored data in the table, you may see them using the 'SELECT' statement.

19
select * from employees;

You can retrieve all the data in a table with the above manner or selectively call back only the
data in the desired columns as follows by presenting the names of columns with commas:

select first_name, department, salary from employees;

20
Let's add some more data to the table because they may be needed to learn other queries in
the following chapters.

insert into employees (first_name, last_name, department, salary, is_admin)


values ('Andrew', 'Barton', 'marketing', 73000, 0),
('Robert', 'Alcott', 'finance', 71000, 0),
('James', 'Franklin', 'hr', 82000, 0),
('Clara', 'Jackson', 'hr', 100000, 1),
('James', 'Moon', 'management', 98000, 1),
('Ansel', 'Washington', 'management', 82000, 0),
('Grace', 'Monroe', 'finance', 84000, 0),
('Amelia', 'Adams', 'sales', 72000, 0),
('William', 'Earhart', 'service', 68000, 0);

4-11. DISTINCT <name of column>

A table typically has multiple columns. And we need to know how diverse data exist in a
particular column. It means checking how many cases are there, and the query that can be
used for this is 'DISTINCT.' When using 'DISTINCT,' you will only see non-duplicated data
in the specified column. Let's run the following statement.

select distinct department from employees;

21
Using the 'DISTINCT' keyword, you will know only six kinds of data exist in the
'departments' column. And if you give more than one column name like below, you can see
the maximum number of combinations that the specified columns can produce.

select distinct department, is_admin from employees;

As you can see in the picture above, the number of combinations that the 'department' and
'is_admin' column can produce is eleven. It's because 'is_admin' may have the value of '0' or '1,'
which means the 'marketing' department with the 'is_admin' value of '0' is considered a
different combination with the 'is_admin' value of '1.' Some other columns were also
counted two for the same reason.

22
4-12. LIMIT <number of desired data>

By default, the SQL queries target all stored data. But you may not always need all of them.
Use the 'LIMIT' keyword if you only want to see a certain number of data. It is possible to
retrieve only the desired number of data by attaching 'LIMIT' to the end of the 'SELECT'
statement as follows:

select department from employees limit 5;

The query above will retrieve only the


first five data in the 'department'
column in the 'employees' table.

However, merely retrieving data may


return duplicate value like 'marketing,'
as shown in the picture on the left. It's
because we only considered the number
of returned data, not its redundancy.
Then, what should we do if we want to get a result that doesn't have any duplication of data?
Using 'LIMIT' and 'DISTINCT' together will clear the issue.

select distinct department from employees limit 5;

Unlike the result shown above,


now you see that the duplicate
value has been excluded by
'DISTINCT.' However, what
we need in real life is probably
a little more sophisticated than
this. For example, what do we
have to do if we want to see
only three data starting from
the second record? The following syntax will make it possible.

23
LIMIT <off-set>, <number of desired data>

select distinct department from employees limit 2, 3;

When you execute the above statement, it will bring out three data in the table, starting from
the third record. And you may wonder why it starts from the third data even though you
wrote '2.' It's because the first counting number in SQL is not '1' but '0.' Therefore, if you
want to see data starting from the fifth, you should write 'limit 4, n.'

24
4-13. ORDER BY <name of column>

You can consider using the 'ORDER BY' operator to sort out the results returned by the
'SELECT' statement.

select * from employees order by salary;

The above query will show all the data in the 'employees' table, sorted by the values in the
'salary' column. This operation is ascending by default unless you specify another option.
That is, it sorts the data from the smallest to the largest.

As I said, the default way of sorting is ascending (ASC). However, if necessary, you may
make your result arranged in descending order (DESC). 'Ascending Order' is the way that
shows the data from small to large, and 'Descending Order' is from large to small.

select * from employees order by salary asc;


select * from employees order by salary desc;

25
'ORDER BY' is not only available when sorting based on one column. You may also use it
over several columns, in which case you only need to separate the columns with a comma.
When you write the query as follows, the data will be sorted based on the column presented
first and then re-aligned based on the second column.

26
select * from employees order by salary, is_admin;

4-14. Multiple Queries

It is possible to execute queries one at a time, but SQL also allows multiple queries to be
used simultaneously.

select first_name from employees; select department from employees;

You may write the above statement as below, and both perform nothing different:

select first_name from employees;


select department from employees;

27
Like above, you can write several query statements not only in one line but in several lines. It
is possible because, in SQL, a semicolon means the end of a query statement. However, of
course, this is a bad idea. You'd better make it a habit to present only one query statement
on one line.

No matter how you write your statements, the results will be displayed on separated tabs if
you use HeidiSQL as your tool.

4-15. WHERE

The keyword, 'WHERE,' is used to retrieve only data out of a table by the given condition(s).

SELECT <name of column> FROM <name of table> WHERE <condition(s)>

To use 'WHERE,' you should present at least one condition. If you want to give multiple
conditions, you should use the 'AND' or 'OR' keyword between the conditions. When
'AND' is used, it will return only data that satisfies all the given conditions, and with 'OR,' it
will return all of the results that meet any of the given conditions. The following statement
will extract all the data only belonging to the sales department.

28
select * from employees where department='sales';

As I mentioned before, several conditions can be presented at once to access the desired data more
accurately. The statement below will extract only data from the sales department for the employee
named 'Susan.'

select * from employees where first_name='susan' and department='sales';

The following statement will retrieve the first names of employees from the 'employees' table,
either in the 'sales' or 'hr' department in descending order.

select first_name, department from employees


where department='sales' or department='hr'
order by department desc;

29
As in the above, you need to write down the field names you want to get in the result,
putting a comma between field names. Changing the keyword 'OR' to 'AND' will return a
completely different outcome like below. Therefore, you'd better pay extra attention when
choosing between the 'AND' and 'OR' keywords.

select first_name, department from employees


where department='sales' and department='hr';

When 'AND' is used, there is no return because the 'employees' table we created doesn't
have a person who belongs to two departments simultaneously.

30
4-16. ALTER TABLE

4-16-1. ADD <name of column> <type of data>

'ALTER TABLE' is for adding, deleting, or modifying column(s) in a table that already exists.
Besides, with 'ALTER TABLE,' you can add or delete various constraints ― 'Constraints' are
covered in chapter 8-13. Here we will only deal with adding, deleting, and modifying new
columns.

ALTER TABLE <name of table> ADD <name of column> <type of data>;

The following query will add a new column to the 'employees' table to store the employee's
gender information.

alter table employees add gender varchar(1);

select * from employees;

This time, we only added a new column but did not enter any data. So each field is filled
with a 'NULL' value just for now.

31
〔 DB Terms 6 〕 What is 'NULL' value?

When you add a new column or row to a table, you may not include actual data. In this
case, the field will have a null value by default, which is different from the number '0' or a
space character. It is just an empty state without having any data value.

4-16-2. DROP COLUMN <name of column>

In contrast to the 'ADD' keyword, 'DROP' allows you to delete column(s) from a table.
Unlike adding a new column, you only need to name the column you want to eliminate
without presenting its data type.

ALTER TABLE <name of table> DROP COLUMN <name of column>;

alter table employees drop column is_admin;

select * from employees;

Executing the above statement, we will see that the column 'is_admin' that existed in the
'employees' table has disappeared.

32
4-16-3. MODIFY COLUMN <name of column> <type of data>

Each column shall declare the data type to be stored when it is first created. However, when
you operate a database, you sometimes need to revise the data type, and what you use in this
case is the 'MODIFY' keyword.

ALTER TABLE <name of table> MODIFY COLUMN <name of column> <type of data>;

alter table employees modify column gender varchar(6);

When we create the 'gender' column, its initial data type was 'varchar(1),' which means the
column can store only one letter. However, the above query will change the column to a size
that can hold up to six characters.

4-16-4. CHANGE COLUMN <name of column> <type of data>

The name of each column is declared when the table is first created. However, adding tables
as needed can create columns with the same name in other tables, leading to difficulties in
managing DB. For any reason, 'CHANGE COLUMN' may be used to rename the already
defined column, and omitting the keyword 'COLUMN' won't make any difference.

ALTER TABLE <name of table>


CHANGE COLUMN <current name of column> <new name of column> <type of data>;

= ALTER TABLE <name of table>


CHANGE <current name of column> <new name of column> <type of data>;

alter table employees change id eid int auto_increment;


select * from employees;

After executing the statement above, you will find that the name of the 'id' column now has
the name of 'eid.'

33
4-17. UPDATE

DB operation requires data modification quite often. It may be due to a simple typo or
because of changes in address or phone number. Whatever the reason is, the 'UPDATE'
statement will alter the data values that exist in the table. The syntax of 'UPDATE' will be
like the following. The result is the same whether the line is changed or not when writing the
statement.

UPDATE <name of table>


SET <name of column_1> = <value of data_1>, <name of column_2> = <value of data_2> ...
WHERE <condition(s)>;

Now let's enter the gender information in the table that has been left with 'NULL' values.

update employees set gender='male' where eid=1;

34
Particular attention should be paid to the 'WHERE' condition when using the 'UPDATE'
statement. If you omit the condition, all the data values in the column you indicated will be
changed at once, as seen in the picture below, and it may not be what you intended.

update employees set gender='male';


select * from employees;

We now know how to change one value in a column and all the data values at once. Then, is
there any way to pick only some records and modify their values? You may achieve this by
using the 'WHERE' conditional statement as follows:

update employees set gender='female'


where eid=4 or eid=5 or eid=6 or eid=10 or eid=13 or eid=14;

select * from employees;

Executing the above statement will change the gender information to 'female' only in the
records with 'eid' of 4, 5, 6, 10, 13, and 14.

35
When using the 'UPDATE' statement, there is no rule about the order that data should be
presented. You only need to match the data values with the names of the columns to which
the data should go. Therefore, the two statements below will perform the same function.

UPDATE employees SET salary=150000, last_name='moon' WHERE eid=11;


UPDATE employees SET last_name='moon', salary=150000 WHERE eid=11;

〔 DB Terms 7 〕 ALTER vs. UPDATE

While the 'ALTER' statement restructures a table, the 'UPDATE' statement modifies the
actual data values stored in a table.

36
4-18. DELETE

The query 'DELETE' removes a record that exists in a table. It is not just to delete the data in a field,
but to delete the entire row, a record.

DELETE FROM <name of table> WHERE <condition(s)>;

Executing the statement below will remove the record of an employee named 'James Moon'
from the table.

delete from employees where first_name='james' and last_name='moon';

Now you may wonder if there is a way to delete all the records with a single statement? Of
course, there is. You just don't present the 'WHERE' condition. It means, if you give no
condition in the 'DELETE' statement, all the records in the table will be gone at once.
Therefore, you should be very careful with the 'WHERE' clause when using 'DELETE.'

delete from employees;

37
As you see, the above statement will remove all the records in your table like below.

〔 DB Terms 8 〕 DROP vs. DELETE

The difference between 'DROP' and 'DELETE' is that 'DROP' changes the DB structure,
while 'DELETE' only eliminates record(s) without causing a structural change in the DB or
tables. In SQL, the storing of data is made in the form of a record, so merely removing
record(s) does not lead to structural change in the DB.

It is necessary to re-enter the data here to learn other queries. This time, We will add two
more fields for the 'age' and the 'joined date' of employees. Please execute the following
queries.

alter table employees add age int;


alter table employees add joined_date date;

insert into employees (first_name, last_name, department, salary, gender, age, joined_date)
values ('Benjamin', 'Hopper', 'management', 140000, 'male', 46, 20120718),
('George', 'Jefferson', 'marketing', 110000, 'male', 45, 20120718),
('Thomas', 'Anthony', 'marketing', 87000, 'male', 34, 20120718),
('Susan', 'Lee', 'sales', 120000, 'female', 39, 20120718),
('Louisa', 'Alcott', 'finance', 120000, 'female', 37, 20120718),
('Dolley', 'Madison ', 'sales', 88000, 'female', 29, 20140102),
('Andrew', 'Barton', 'marketing', 73000, 'male', 26, 20140102),
('Robert', 'Alcott', 'finance', 71000, 'male', 28, 20150927),

38
('James', 'Franklin', 'hr', 82000, 'male', 30, 20161114),
('Clara', 'Jackson', 'hr', 100000, 'female', 36, 20161211),
('James', 'Moon', 'management', 98000, 'male', 37, 20170803),
('Ansel', 'Washington', 'management', 82000, 'male', 35, 20170803),
('Grace', 'Monroe', 'finance', 84000, 'female', 31, 20181001),
('Amelia', 'Adams', 'sales', 72000, 'female', 32, 20181001),
('William', 'Earhart', 'service', 68000, 'male', 25, 20200930);

select * from employees;

After executing the above queries, you will find a thing different from the previous table; the
number in the 'eid' column defined as 'auto_increment' starts with '16' instead of '1.' In other
words, the values calculated by the constraint of 'auto_increment' are not getting reset even
after their records are gone.

39
4-19. LIKE, NOT LIKE

Now, you will learn more elaborate usage of the 'WHERE' clause. You can use the
'WHERE' conditional statement with various operators, which gives you more accurate
access to the data you want. If you don't know the exact values of data you're looking for, or
if you know only some portion of them, the 'LIKE' and 'NOT LIKE' operators will help
you a lot. The next statement will retrieve records which has the last name starting with 'J.'

select * from employees where last_name like 'j%';

Contrary to the 'LIKE' operator, the 'NOT LIKE' operator selectively shows only records
that do not have values that meet the given condition(s).

select * from employees where last_name not like 'j%';

40
In the output you can see above, no employee with the last name starting with 'J' is visible.

The following query will retrieve the data, which has five letters and whose value starts with
'a' and ends with 's.'

select * from employees where last_name like 'a_ _ _s';

The above conditional statement uses a single quote (') because the condition is for string
data; you don't use this for numbers. Besides, to represent an apostrophe used in words like
can't in English, you should use a single quote twice in a row as below.

... where string = 'can''t';

If you are familiar with DOS, you must have noticed that the special characters used above
are similar to the wildcards in DOS. That's right. '%' performs the same as '*,' and '_' has
the same function as '?' in DOS. In terms of representing any character, '%' and '_' are the
same, but '%' does not care about the number of characters, while '_' means only one
character.

Thus, 'a%' may include America, Africa, and Asia, but 'a_' will not indicate any of those.
It's because 'a_' refers to data beginning with 'a' with only one more letter follows (two
characters in total). Therefore, to have 'Asia,' there must be three underscores like 'a_ _ _.'

41
5. Comparison Operators

The 'WHERE' statement is an essential tool for database management. To use this statement
more accurately and effectively, SQL allows the use of the various comparison operators
with it:

Operator Description

= Checks if the values of two operands are equal. If they are, it returns true.

Checks if the values of two operands are not equal. If they are not,
!=
it returns true.

<> Same as '!='

Checks if the value of left operand is greater than that of right operand.
>
If yes, it returns true.

Checks if the value of left operand is greater than or equal to the value of
>=
right operand. If yes, it returns true.

Checks if the value of left operand is less than the value of right operand.
<
If yes, it returns true.

Checks if the value of left operand is less than or equal to the value of
<=
right operand. If yes, it returns true.

Searches for the data within the range of the values, given the minimum
BETWEEN
and maximum values.

NOT Searches for the data out of the range of the values, given the minimum
BETWEEN and maximum values.

Searches for the data which has any of the given values in the specified
IN
column.

42
Searches for the data which doesn't have any of the given values in the
NOT IN
specified column.

Searches for the data that matches the given pattern, generally used with
LIKE
a wildcard.

Searches for the data that doesn't match the given pattern, generally used
NOT LIKE
with a wildcard.

Presents multiple conditions in a query statement; retrieve only data that


AND
meet all the given conditions.

Presents multiple conditions in a query statement; retrieve all the data that
OR
meet any given conditions.

In the case of 'IN' and 'NOT IN,' the conditions must be enclosed with parentheses, and a
comma should separate each condition.

select * from employees where first_name != 'james' and last_name not like 'a%';

This query will retrieve the data except for both the employees named 'James' and whose last
name starts with 'A.'

43
At first glance, the operator '=, !=' looks just like the operator 'LIKE, NOT LIKE.'
However, there is a significant difference. While 'LIKE, NOT LIKE' operators can use
wildcards such as '%' and '_,' '=, !=' operators cannot use them.

The following statement will return only records of employees in their 20s.

select * from employees where age < 30 and age >= 20;

If you want to present a condition having a continuous range, as in the statement above, the
'BETWEEN' operator may be more straightforward.

select * from employees where age between 20 and 29;

The following statement uses the 'IN' operator to bring only records of employees whose
ages are 25, 35, and 45.

44
select * from employees where age in (25, 35, 45);

Without the 'IN' operator, we might have to use too many '=' operators. That's why the 'IN'
and 'NOT IN' operators are useful. You may think 'IN' operator as a bundle of several '='s
and the 'NOT IN' operator as a bundle of '!='s.

Also, it is possible to present several conditions at once as follows:

select * from employees where (department in ('management', 'hr'))


and age not between 20 and 29;

The above query retrieves only records of the employees from the 'management' or 'hr'
department, excluding those in their 20s. Particularly noteworthy are the blue-colored
parentheses, which set the priority of the conditions. If there is something to consider before
any other condition(s), then you may put the condition(s) into parentheses like that.

45
6. Arithmetic Operators

Is DB only possible to save and retrieve data? Of course, they are the primary services and
why DB exists. However, if the data stored in column(s) are numeric, such as integer and
real, you can do some basic arithmetic operations with SQL.

Operator Description

Addition + Adds value to the operand.

Subtraction ― Subtracts right-hand operand from left-hand operand.

Multiplication * Multiplies a value on the operand.

Divides left-hand operand by right-hand operand,


Division /
and returns the quotient.

Divides left-hand operand by right-hand operand,


Modulus %
and returns the remainder.

select first_name, last_name, age + 1, salary + 10000 from employees;

The above query will show you the ages of employees after adding '1' and their annual
salaries after adding '10,000' dollars. And it is crucial to remember that using arithmetic
operators provided by SQL only temporarily affects the output; it does not permanently
change the actual data values. You should use the 'UPDATE' statement if you want a
permanent change in the data value.

46
Please look carefully at the figures below and see what result each arithmetic operator
returns.

As in typical mathematics, parentheses give priority to calculations.

47
7. Functions

In addition to simple arithmetic operations, SQL provides various functions as well. And it is
possible to manipulate the output by using them. When employing a function, you should
present the name of the column or the data value in parentheses, to which the function
applies. In this chapter, we will not study all the functions but the most frequently used ones.

7-1. String Functions

Function Description

CHARACTER_LENGTH Returns the length of a string in characters.

CHAR_LENGTH Same as 'CHARACTER_LENGTH'

LENGTH Returns the length of a string in bytes.

CONCAT Binds two or more expressions together.

CONCAT_WS Binds two or more expressions together with a separator.

LCASE Converts the specified string(s) to lower-case.

LOWER Same as 'LCASE'

48
UCASE Converts the specified string(s) to upper-case.

UPPER Same as 'UCASE'

Extracts a specified number of characters from a string,


LEFT
starting from the left.

Extracts a specified number of characters from a string,


RIGHT
starting from the right.

Extracts a specified number of characters from a string


SUBSTRING
from a given position.

SUBSTR Same as 'SUBSTRING'

Removes leading and trailing spaces (not in the middle)


TRIM
from strings.

The following examples are showing some cases in which functions work.

select * from employees where (char_length(first_name) <= 5);

The above query will only return the records whose first names are not more than five
characters long.

49
On the other hand, the statement below will only return records of employees whose names
are more than six characters long.

select * from employees where (char_length(first_name) > 5);

And the following query statement will show, in the table, how many characters each first
name has and how many bytes each of them holds.

select first_name, char_length(first_name), length(first_name) from employees;

50
select concat('the salary of ', first_name, ' ', last_name, ' is ', salary) from employees;

As you can see above, the 'CONCAT' function allows you to pre-determine the return
format in advance. While using the 'CONCAT_WS' function, you will get a little bit different
result by specifying a 'separator' as the first parameter for the function.

select concat_ws("$", "the salary of ", first_name, " ", last_name, " is ", salary)
from employees;

Note that, with the 'CONCAT' function, we used single quotes(' ') to express a string, but
with the 'CONCAT_WS,' double quotes(" ") were used to do the same thing. It means,
when expressing a string in SQL, you can use either single or double quotes, and there is
no difference between them.

51
The query below will retrieve four letters from the employee's name, starting from the
second character.

select substr(first_name, 2, 4) from employees;

There are so many built-in functions available with MariaDB. If you want to know more
about them, you can check it out on the link below.

https://mariadb.com/kb/en/built-in-functions/

52
7-2. Numeric Functions

Function Description

ABS Returns the absolute value of the specified number.

AVG Returns the average value of the specified column.

COUNT Returns the total number of data stored in the specified column.

Returns the integer value of the remainder in the modulus operation,


MOD
as with '%.'

DIV Returns the integer value of the quotient in the division, as with '/.'

MAX Returns the maximum value in the specified column.

MIN Returns the minimum value in the specified column.

POWER Returns the value of a number raised to the power of another.

POW Same as 'POWER'

Generates a random number in ranges greater than '0' and less


than '1.'
RAND
* RAND(seed): when giving 'seed,' it generates the same number repeatedly,
but if not giving 'seed,' it keeps generating different numbers

Returns the maximum integer value less than or equal to


FLOOR
the specified number.

53
Returns the minimum integer value greater than or equal to
CEILING
the specified number.

ROUND Returns the rounded value for the specified number.

Indicates whether the specified number is positive or negative:


SIGN
positive number returns '1,' negative number '–1.'

SQRT Returns the square root value for the specified number.

SUM Returns the sum of the values stored in the specified column.

Predetermines the form when showing the result of a function,


FORMAT and it will round the lowest number of digits, and the result will
be character data, not numeric.

Predetermines the form when showing the result of a function,


TRUNCATE and it will not round the lowest number of digits, and the result
will be numeric data, not character.

You should note that numeric functions like 'SQRT, AVG, SUM, MIN, MAX' fall a letter
or even a string into the calculation category, which may lead to an unexpected result.

select avg(age), avg(salary) from employees;

This query statement will show you


what the average age and salary of the
employees are.

54
The below query will show how many employees exist based on their first names stored in
the table, and it includes the data even with the same value in the calculation.

select count(first_name) from employees;

As shown in the figure below, the value of 33 divided by 2 (33 / 2) would be '16.5'. In
comparison, even if doing the same calculation with the same numbers, '33 DIV 2' results in
'16.' It is because the largest integer number in the quotient is '16.'

select 33 / 2, 33 div 2, 33 % 2, 33 mod 2;

The following query statement is showing both the highest and lowest annual salaries in the
'employees' table.

select max(salary), min(salary) from employees;

55
As mentioned before, the 'RAND( )' function may or may not be used with the number
called 'seed.' However, if you give a 'seed' as shown below, you will always get the same
result, but if you don't, you will get a different result every time you execute the function.

select rand(2), rand(2), rand( ), rand( );

The maximum integer value less than the number '17.54' is '17,' and the nearest integer value
greater than '17.54' is '18.' And if you round up '17.54,' it becomes '18.' And those are how
the functions 'FLOOR,' 'CEILING,' and 'ROUND' work.

select 17.54, floor(17.54), ceiling(17.54), round(17.54);

The query statement below shows the average annual salary of employees again, but we use
the functions 'FORMAT' and 'TRUNCATE' together this time. The two functions have
something in common; they can determine how many decimal places to show when
expressing numbers.

select avg(salary), format(avg(salary), 1), truncate(avg(salary), 1) from employees;

56
However, there is a significant difference between 'FORMAT' and 'TRUNCATE.' As you
can see above, if you use 'FORMAT,' the output has left-hand alignment in green (string
data representation). On the other hand, it has right-hand alignment in blue (numeric
data representation) when you use the 'TRUNCATE' function. In short, 'FORMAT'
returns the result in string type and 'TRUNCATE' numeric type.

7-3. Date Functions

Recording the date and time when data is created, modified, or deleted is crucial because the
purpose of operating DB is to manage data. Therefore, it is no wonder why SQL provides so
many functions related to date and time.

Function Description

CURRENT_DATE Returns the current date in the form: yyyy-mm-dd.

CURRENT_TIME Returns the current time in the form: hh:mm:ss.

Returns the current date and time in the form:


SYSDATE
yyyy-mm-dd hh:mm:ss.

Returns the current date and time in the form:


LOCALTIME
yyyy-mm-dd hh:mm:ss.

57
Returns the current date and time in the form:
NOW
yyyy-mm-dd hh:mm:ss.

DATE Extracts the date information from a date-time expression.

TIME Extracts the time information from a date-time expression.

Extracts the hour part in the date information from a date-time


HOUR
expression.

Extracts the minute part in the date information from a date-


MINUTE
time expression.

Extracts the second part in the date information from a date-


SECOND
time expression.

Returns the value of the date information after adding the


DATE_ADD specified day(s) or time.
* Refer to the instructions below for the available units

Returns the value of the date information after subtracting


DATE_SUB
the specified day(s) or time.

DATEDIFF Calculates the number of days between the two given dates.

Specifies the format that represents the date.


DATE_FORMAT
* Refer to the instructions below for the available formats

DAYNAME Returns the name of the day corresponding to the given date.

MONTHNAME Returns the name of the month corresponding to the given date.

58
DAYOFYEAR Calculates how many days have elapsed in the year.

WEEKOFYEAR Calculates how many weeks have elapsed in the year.

AVAILABLE UNITS THAT CAN BE USED WITH 'DATE_ADD( )' FUNCTION

MICROSECOND, SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, YEAR,


and so forth.

e.g. DATE_ADD("2019-12-31", INTERVAL 3 WEEK);

AVAILABLE FORMATS THAT CAN BE USED WITH 'DATE_FORMAT( )' FUNCTION

%a Expresses the abbreviated name of the day: Sun ~ Sat


%W Expresses the full name of the day: Sunday ~ Saturday
%D Expresses the name of the day in the ordinal form: 1st, 2nd, 3rd, etc.
%d Expresses the name of the day in the cardinal form: 1, 2, 3, etc.
%b Expresses the abbreviated name of the month: Jan ~ Dec
%M Expresses the full name of the month: January ~ December
%m Expresses the month in the two digits cardinal form: 01 ~ 12
%Y Expresses the year in four digits: YYYY
%y Expresses the year in two digits: yy
%j Expresses how many days have elapsed in the year: 0 ~ 366
%u Expresses how many weeks have elapsed in the year,
considering the first day of a week is Monday: 0 ~ 53
%U Expresses how many weeks have elapsed in the year,
considering the first day of a week is Sunday: 0 ~ 53
%p Expresses whether it is forenoon or afternoon: AM, PM
%r Expresses time in 12-hour notation with AM/PM: hh:mm:ss AM/PM
%T Expresses time in 24-hour notation: hh:mm:ss
%s Expresses the second in two digits: 00 to 59

* When using these formats, the upper and lower case letters may have different meanings.

59
The query below obtains the current date and time with the 'NOW' function, and uses the
'DATE' function to extract only the date information from them, then adds another 100
days to it. The combination of several functions will make it easier to access the desired
information.

select date_add(date(now()), interval 100 day);

If you want to subtract 100 days, you may give a negative number after the keyword
'interval' or use the 'DATE_SUB' function. And there will be no difference.

select date_add(date(sysdate( )), interval -100 day);


= select date_sub(date(sysdate( )), interval 100 day);

select datediff(now(), '2000-01-01'), datediff(now(), 20000101);

As shown in the figure above, the date can be presented in a string format ('2000-01-01') or a numeric
format (20000101). Either way, the result is the same. Besides, as I mentioned before, you may use
double quotes(" ") in a string format, which is also not considered different from single
quotes(' ') in SQL.

60
The statement below extracts the current date information and shows it in the desired format.

select current_date, date_format(current_date(), '%M %D, %Y, %W');

select current_date, dayname(current_date() + 3), monthname(current_date());

As in the above query, you may apply arithmetic operations when using date functions, and
you may check how many days or weeks have elapsed in the year as follows:

select current_date(), dayofyear(current_date()), weekofyear(current_date());

61
8. Advanced SQL Queries

8-1. AS

The 'AS,' also called 'Alias,' assigns a temporary name to a table or a column when returning
the result; it makes the output more readable and understandable.

select first_name, last_name from employees;


select first_name as given_name, last_name as family_name from employees;

The 'AS' keyword renames the field in the result table as desired. It is simple yet useful, so
you may need it many times.

62
You cannot use a blank space in SQL like 'given name.' For this reason, the above
statement uses an underscore between 'given' and 'name' like 'given_name.'

You may use the 'AS' keyword not just to change a field name but also to rename a table
itself. If you want to change the name of a table to an easier and simpler one, try it as follows.

To rename a table, use 'AS' after the 'FROM' keyword. It means that using the 'AS' keyword
before 'FROM' differs from using it after 'FROM.'

select emp.first_name, emp.last_name from employees as emp;

When using the simplified table name, you must follow the naming rule as in
'name_of_table.name_of_column.' And the period(.) used between the table name and the
column name is called the 'Dot Operator,' and 'Dot Operator' will have a crucial role in the
'JOIN' statement. We will study about it in the chapter of 8-4 and 8-5.

When using the dot operator, it is used in the order from the larger concept to the smaller
concept as follows: DB.Table.Column.

63
8-2. Putting Comments

No matter what program you create in what language, documentation cannot be emphasized
too much. The most basic way of documentation is, of course, putting comments. If you
keep recording what purpose each query is made for, it will help not only other developers
but also yourself. Therefore, making a habit of putting as many comments as possible.

As with other programming languages, SQL offers two types of comments: single-line
comment and multi-line comment.

8-2-1. Single-line Comment

If you want to insert a single line comment, write down the hyphen(―) twice in a row at the
very front of the line. Comments will not affect the performance or the result of the query.

-- Showing the salary and the joined date of each employee


select first_name, last_name, salary, joined_date from employees;

64
8-2-2. Multi-line Comment

If you write multi-line comments, your queries may become even easier to understand. To
put a multi-line comment, you need to start your comment with the '/*' symbol and end
with the '*/' symbol. And you are allowed to use as many lines as you want for your
comment.

/* Calculating the average annual salary and the average age of the employees:
the first column shows the average annual salary, and the second column shows
the average age of the employees, both with a single decimal place. */

select format(avg(salary), 1), format(avg(age), 1) from employees;

As with a single line comment, a multi-line comment does not affect the performance and
outcome of the query in any matter.

Let's create a new table called 'performance' to learn more queries. Please write and execute
the queries below.

/* This table is for recording the performance of all employees for three years.
The evaluation score is independent of the department to which he/she belongs:
the score is out of 100. */

use mydb;

65
create table performance
(
pid int auto_increment,
first_name varchar (20),
last_name varchar (20),
department varchar (20),
year_2018 double (3,1),
year_2019 double (3,1),
year_2020 double (3,1),
primary key (pid)
);

insert into performance (first_name, last_name, department, year_2018, year_2019,


year_2020)
values ('Benjamin', 'Hopper', 'management', 74.3, 82.7, 81.3),
('George', 'Jefferson', 'marketing', 73.9, 85.2, 86.6),
('Thomas', 'Anthony', 'marketing', 70.8, 69.2, 75.9),
('Susan', 'Lee', 'sales', 76.1, 80.0, 82.2),
('Louisa', 'Alcott', 'finance', 83.8, 78.8, 75.2),
('Dolley', 'Madison ', 'sales', 62.9, 63.1, 59.8),
('Andrew', 'Barton', 'marketing', 50.4, 53.4, 66.7),
('Robert', 'Alcott', 'finance', 60.8, 63.7, 63.9),
('James', 'Franklin', 'hr', 63.7, 58.6, 56.6),
('Clara', 'Jackson', 'hr', 88.3, 88.8, 90.0),
('James', 'Moon', 'management', 63.2, 49.5, 51.1),
('Ansel', 'Washington', 'management', 74.9, 71.8, 79.3),
('Grace', 'Monroe', 'finance', 79.3, 89.2, 91.2),
('Amelia', 'Adams', 'sales', 71.3, 88.8, 89.7),
('William', 'Earhart', 'service', 70.1, 72.8, 68.4);

66
8-3. Sub-Query

A single query carries out only one function and returns its corresponding result. However,
DB management may require access to data with more sophisticated conditions. In this case,
you can use 'Sub-Query,' which nests a query as a condition for another query.

select first_name, last_name, department, year_2020 from performance


where year_2020 >= (select avg(year_2020) from performance)
order by year_2020 desc;

The above statement retrieves only the names, departments, and employees' evaluation
scores with better-than-average performance based on the year 2020 saved in the
'performance' table. To this end, a query is used, as a condition, within another query, and it
is called 'Sub-Query.' If you want to use a sub-query, you must enclose it with parentheses.

RULES FOR THE USE OF SUB-QUERIES

1. Sub-Queries must be enclosed in parentheses.


2. Sub-Queries shall be located on the right side of the operator.
3. Sub-Queries may be used with the 'IN' operator; however, it is inefficient.
4. 'ORDER BY' operator cannot be used within Sub-Queries.

67
: 'ORDER BY' is about the final output of a query statement. Therefore, it can only be
used once in the main query.

Of course, you may have more than one sub-query in one statement if you need it.

select first_name, last_name, gender from employees


where char_length(first_name) >
(select avg(char_length(first_name)) from employees)
and char_length(last_name) <
(select avg(char_length(last_name)) from employees)
order by first_name asc;

68
8-4. Dot Operator

All the queries that we have studied so far only work in one table. However, in operating
SQL, there must be a case that needs to retrieve and process data from more than one table.
And, that is the moment, you may need a 'Dot Operator.'

To retrieve data from a particular table, you put a 'dot' between the name of the table and
the name of the column as 'table.column.' And If you are to retrieve data from multiple
tables, you need to name them after the keyword 'FROM' with a comma as follows:

select employees.first_name, employees.department, performance.year_2020


from employees, performance
where employees.first_name = performance.first_name;

The above queries retrieve data from two tables. To that end, we present the names of the
tables after the 'FROM' keyword as 'employees, performance.' The 'WHERE' statement is
used to ensure that the same 'first_name' exists in both tables to avoid the duplicated output.

69
The following queries also return the data from both the 'employees' and the 'performance'
tables. And this time, we use the keyword 'AS' to simplify the names of the tables; it is useful
because the more typing you do, the more typos you may make.

select emp.first_name, emp.department, per.year_2020


from employees as emp, performance as per
where emp.first_name = per.first_name;

Now, we may need one more table for the following chapter.

use mydb;

create table promotion


(
pr_id int auto_increment,
first_name varchar(20),
last_name varchar(20),
department varchar(20),
rate double(3,2),
promote_date date,
primary key (pr_id)
);

insert into promotion (first_name, last_name, department, rate, promote_date)


values ('George', 'Jefferson', 'marketing', 1.20, 20210101),
('Susan', 'Lee', 'sales', 1.20, 20210101),
('Andrew', 'Barton', 'marketing', 1.10, 20210101),
('Robert', 'Alcott', 'finance', 1.10, 20210101),
('Clara', 'Jackson', 'hr', 1.30, 20210101),
('Grace', 'Monroe', 'finance', 1.30, 20210101),
('Amelia', 'Adams', 'sales', 1.20, 20210101);

70
8-5. JOIN

With 'Dot Operator,' you can retrieve and manipulate data from multiple tables in a single
query statement. However, you may consider using the 'JOIN' statement to perform the
same thing more delicately. The 'JOIN' statement merges rows from two or more tables
before handling data, enabling more reliable data manipulation.

There are three main ways to join tables.

INNER JOIN Merges data that matches in both the right and left tables.

Returns all data from the left table, merging data that matches in both
LEFT JOIN
the right and left tables.

Returns all data from the right table, merging data that matches in
RIGHT JOIN
both the right and left tables.

8-5-1. INNER JOIN

'INNER JOIN' is the most commonly used form of 'JOIN.'


It extracts and manipulates the only data existing both in two
tables indicated.

Let's re-organize the statement used to study the previous


'Dot Operator' into the 'JOIN' statement.

select employees.first_name, employees.department, performance.year_2020


from employees, performance
where employees.first_name = performance.first_name;

The above queries return the same result as below.

71
select employees.first_name, employees.department, performance.year_2020
from employees inner join performance
on employees.first_name = performance.first_name;

TO PRESENT CONDITION(S) IN 'JOIN' STATEMENT

The 'WHERE' keyword is used to present conditions in the statement that does not have
the 'JOIN' operator. On the other hand, the 'ON' keyword is used to give conditions in the
statement having the 'JOIN' operator.

Then, is it possible to use the 'JOIN' statement across more than two tables? Of course, you
can.

select employees.first_name, employees.last_name,


performance.year_2020, promotion.rate
from (employees inner join performance
on employees.first_name = performance.first_name
and employees.last_name = performance.last_name)
inner join promotion

72
on performance.first_name = promotion.first_name
and performance.last_name = promotion.last_name
and promotion.rate >= 1.2;

The above queries return only those employees who exist all in the 'employees,'
'performance' and 'promotion' tables, and whose salary will get an increment of more than
20%.

You can reorganize the above queries with 'Dot Operators,' which return the same result.

select employees.first_name, employees.last_name,


performance.year_2020, promotion.rate
from employees, performance, promotion
where employees.first_name = performance.first_name
and employees.last_name = performance.last_name
and performance.first_name = promotion.first_name
and performance.last_name = promotion.last_name
and promotion.rate >= 1.2;

73
8-5-2. LEFT JOIN

'LEFT JOIN' returns all the data presented in the left table
even if no data meets the given condition(s) in the right table.
Then, you may think there is no difference from the original
table on the left. Still, there is a clear difference: it does not
just deal with the data on the left table but also considers
which data in the left table forms an intersection with the
right table.

Let's compare the two queries below:

(1) select * from employees


where char_length(employees.first_name) = 5;

(2) select employees.*


from employees left join promotion
on char_length(employees.first_name) = 5
and employees.first_name = promotion.first_name;

74
Without 'JOIN,' like case (1) above, it is impossible to cross-compute two or more tables.
Therefore, it returns only data whose name has five characters long from the 'employees'
table.

However, for the case (2), using 'LEFT JOIN', it is possible to do cross-computations like
'employees.first_name = promotion.first_name.' It first returns data that satisfies the given
two conditions, 'char_length (employees.first_name)=5' and 'employees.first_name =
promotion.first_name,' followed by the rest of the data in the left table that is not satisfied
with the conditions.

75
8-5-3. RIGHT JOIN

It has the same operating principle as 'LEFT JOIN,' but this


time, it is based on the table on the right. It returns the data
that meets the given condition(s), then the rest of the data in
the right side table, even if it doesn't satisfy the condition(s).

Let's again compare the two queries below:

(1) select * from promotion


where char_length(promotion.first_name) = 5;

(2) select promotion.*


from employees right join promotion
on char_length(promotion.first_name) = 5
and employees.first_name = promotion.first_name;

At first glance, it may seem no different from 'LEFT JOIN,' but the returned data is distinct
from what is based on the 'promotion' table. The below is for case (1), and its result has only
the employees in the 'promotion' table whose names are five characters long.

76
The result below is for case (2), and it first returns the data which meets the two given
conditions, followed by the rest of the data in the right table that is not satisfied with the
conditions.

As you see, you get completely different results depending on whether you use 'LEFT JOIN'
or 'RIGHT JOIN.'

77
8-6. UNION

Until now, every 'SELECT' statement has had its own result; I mean, one 'SELECT'
statement returns one result each. However, what if we want to combine two or more results
into one? Is it possible? Yes, it is. And what is used for this is the operators of 'UNION' and
'UNION ALL.'

The 'UNION' operator is used to merge the results of several 'SELECT' statements into one.
And if you use the 'UNION' operator, it automatically excludes the same data from multiple
results. In comparison, the 'UNION ALL' operator wouldn't rule out even the same data
from the results.

Before we begin, we may need to have one more table.

create table employees_jersey


(
jid int auto_increment,
first_name varchar (20),
last_name varchar (20),
department varchar (20),
salary int,
gender varchar(6),
age int,
joined_date date,
primary key (jid)
);

insert into employees_jersey (first_name, last_name, department, salary, gender, age,


joined_date)
values ('John', 'Fitsimmons', 'management', 127000, 'male', 42, 20181226),
('James', 'Jeffries', 'management', 110000, 'male', 39, 20181226),
('James', 'Moon', 'management', 128000, 'male', 35, 20181226),
('Christy', 'Halmich', 'sales', 89000, 'female', 35, 20181226),

78
('Jessica', 'Salandy', 'sales', 88000, 'female', 34, 20181226),
('Regina', 'Riker', 'sales', 73000, 'female', 29, 20191008),
('Greg', 'Hart', 'sales', 72000, 'male', 27, 20191008),
('Jack', 'Tyson', 'service', 69000, 'male', 26, 20191008),
('Marvin', 'Corbett', 'service', 69000, 'male', 28, 20191008),
('Lucia', 'John', 'service', 70000, 'female', 26, 20191008);

It is important to note that the results you intend to merge must have the same number of
columns. Now let's compare the following statements:

select first_name, last_name from employees where char_length(first_name) = 5


union
select first_name from employees_jersey where char_length(first_name) = 5
order by first_name desc;

Executing the above queries will produce an error. The reason is that the number of
columns is unmatched. To solve this problem, you may temporarily use the 'NULL' keyword
to make the same number of columns.

select first_name, last_name from employees where char_length(first_name) = 5


union
select first_name, null from employees_jersey where char_length(first_name) = 5
order by first_name desc;

However, it is certainly more appropriate to match both the name and number of columns
than just to use the 'NULL' keyword.

select first_name, last_name from employees where char_length(first_name) = 5


union
select first_name, last_name from employees_jersey where char_length(first_name) = 5
order by first_name desc;

79
As showing above, there is no duplicate data in the merged result since you used the
'UNION' operator. However, if you use the 'UNION ALL' operator, you may get a
different outcome.

select first_name, last_name from employees where char_length(first_name) = 5


union all
select first_name, last_name from employees_jersey where char_length(first_name) = 5
order by first_name desc;

80
Like above, the 'UNION ALL' operator allows you to view all data that exclude none. That's
why you see the data 'James Moon' twice. And sometimes it may be necessary. Therefore, it
is your choice of which one to use, 'UNION' or 'UNION ALL.'

8-7. GROUP BY

'GROUP BY' calculates the number of records having the same value. For example, it is
useful to figure out how many employees are of the same age and how many employees
receive the same salary amount. For this purpose, the keyword 'GROUP BY' is often used
with aggregate functions (COUNT, SUM, AVG, MIN, MAX, ...).

select salary, count(eid) from employees


where salary >= 100000
group by salary
order by salary desc;

Using 'GROUP BY,' as seen above, it is easy to check the distribution of employees' salaries:
two people receive $120,000 a year, one person receives $140,000 a year, and so on.

81
8-8. HAVING

Both 'HAVING' and 'WHERE' are used to present conditions in SQL statements. However,
the 'WHERE' clause does not allow aggregation functions such as COUNT, SUM, AVG,
MIN, MAX, and so forth., whereas the 'HAVING' clause allows you to use them.

So, the 'WHERE' clause below, which has one of the aggregation functions, 'COUNT( )'
causes an error.

select joined_date, count(joined_date) from employees


group by joined_date
where count(joined_date) >= 2;

In other words, if you need to have an aggregation function(s) in your condition, you should
use 'HAVING' instead of 'WHERE,' like below.

select joined_date, count(joined_date) from employees


group by joined_date
having count(joined_date) >= 2;

However, please don't get me wrong. I'm not saying that the 'HAVING' clause must use an
aggregation function. Using the aggregation function in the 'HAVING' clause is only your choice.

82
The two statements below will return the same result. It means, when an aggregation
function is not used, the difference between the 'WHERE' and the 'HAVING' clauses may
become ambiguous.

select * from employees where first_name like 'a%';


select * from employees having first_name like 'a%';

Then, what is the exact difference between 'WHERE' and 'HAVING'? I mean, If
'HAVING' not only can work like 'WHERE' but also be able to use aggregation functions,
you might think that there is no reason for 'WHERE' to exist in the first place; The
difference between the two needs to be clearly understood in this very sense.

The 'WHERE' clause places the condition(s) on the selected column, while the 'HAVING'
clause places the condition(s) on the group generated by the 'GROUP BY.' Therefore,
'HAVING' is closely related to the 'GROUP BY' clause. Because of this, 'WHERE' must
precede the 'GROUP BY,' and the 'HAVING' be placed after 'GROUP BY.'

The following statement will lead to an error because the 'HAVING' clause precedes
'GROUP BY.'

select joined_date, count(joined_date) from employees


having count(joined_date) >= 2
group by joined_date;

However, no error would occur if the 'HAVING' clause is placed after 'GROUP BY' as
follows:

select joined_date, count(joined_date) from employees


group by joined_date
having count(joined_date) >= 2;

83
8-9. INSERT INTO SELECT : Cloning Table

To copy some or all of the data to another table, you use the 'INSERT INTO SELECT'
statement.

In order to copy a table, the target table must exist before receiving the data, and the number
of columns and the data types must match ― not necessarily the names of columns. If you
copy data to the table already having data, the new data will be added at the end of the table
without deleting any data already in it.

INSERT INTO <name of target table (column1, column2, column3, ....)>


SELECT <column1, column2, column3, ...>
FROM <name of source table>
WHERE <condition(s)>

Let's make a new table to see how it works.

create table employees_backup


(
bk_id int auto_increment,
first_name varchar (20),
last_name varchar (20),
department varchar (20),
salary int,
gender varchar(6),
age int,
joined_date date,
primary key (bk_id)
);

In the newly created table, the first column was named 'bk_id,' not 'eid.' As mentioned
earlier, it is okay because the data types must match between the tables, but the names do
not require to match each other.

84
Now we will copy some of the data from the 'employees' to the 'employees_backup' table.

insert into employees_backup (bk_id, first_name, last_name, department)


select eid, first_name, last_name, department from employees;

select * from employees_backup;

As in the above figure, some columns are filled with 'NULL' because we didn't take over all the data.
Now, let's see what is happening if we copy the rest of the columns, salary, gender, age, and
joined_date, into this table.

insert into employees_backup (salary, gender, age, joined_date)


select salary, gender, age, joined_date from employees;

select * from employees_backup;

The statement above will not make the data fill the places with 'NULL' values in the previous
figure. Instead, it adds new rows and copies data in them.

85
The previous two statements copied only a portion of the data from the original table. If
what you want is only a part of the data, you list the desired columns in the parentheses with
commas. However, if you're going to create a complete backup table, you must take over all
the data at once with one query statement like below, and this time, you don't use
parentheses:

insert into employees_backup


select * from employees;

select * from employees_backup;

86
8-10. RENAME TABLE

While managing DBs, you may repeat the process of creating and erasing tables. And for
effective management, you may have to change the name of an existing table. In this very
case, you will need the query, 'RENAME TABLE.'

RENAME TABLE <current name of table> TO <new name of table>

use mydb;
show tables;

As shown in the figure on the left, there are five tables


in 'mydb.' Among them, I'm going to change the name
of the 'employees' table to 'employees_miami.'

rename table employees to employees_miami;


show tables;

After executing the query, you can


not see the table named 'employees'
any longer. Instead, there is a new
table called 'employees_miami.' The
name of the table is changed.

87
8-11. Temporary Table

A temporary table provides an excellent way to store and process the intermediate results of
various queries. Unlike the usual tables used so far, a temporary table is automatically gone at
the end of the session. If you access a DB server through an external program, the
temporary table exists only while the program remains connected. Therefore, it can be handy
unless you need to store data permanently.

CREATE TEMPORARY TABLE <name of table>


(
name_of_column data_type (size),
name_of_column data_type (size)
);

create temporary table temp


(
id int,
nick_name varchar(20)
);

insert into temp (id, nick_name)


values (1, 'Ironman'),
(2, 'Wolverine'),
(3, 'Hulk');

show tables;

Executing the statement creates a table named 'temp' for sure. And it is all possible to insert,
manipulate, delete, and control the data in the table. Nevertheless, when you run 'SHOW
TABLES,' which shows all the DB tables, you will not see the table named 'temp.'

88
By default, all the temporary tables are deleted by the DB server when your database
connection is terminated. However, you can still delete your temporary table(s) using the
'DROP TABLE' command anytime you want.

drop table temp;

8-12. CASE

If you use the 'CASE' statement, It is convenient for you to present various conditions and
receive different results for each condition. and it keeps the following syntax:

CASE
WHEN <condition_1> THEN <result_1>
WHEN <condition_2> THEN <result_2>
WHEN <condition_n> THEN <result_n>
ELSE <default result>
END;

89
As in other programming languages, the 'CASE' statement leaves the code block as soon as
it satisfies any given conditions. It means if the first condition is 'true,' the following
conditions are no longer checked. The 'ELSE' clause will be carried out when no data
satisfies a condition. And you may omit the 'ELSE' clause because it is not compulsory.

select first_name, last_name, salary,


case
when age between 20 and 29 then 'in his/her twenties'
when age between 30 and 39 then 'in his/her thirties'
when age between 40 and 49 then 'in his/her forties'
end
from employees_miami

It would help if you did not miss the fact that there is a comma after 'salary' on the first line,
making the block made by 'CASE' the fourth column.

The following statement will sort the 'employees_miami' table by the column 'gender.' But if
the 'gender' column has no data, then it will sort the table by the 'age' column.

90
select * from employees_miami
order by
case
when gender is null then age
else gender
end;

As shown above, you may put the 'CASE' statement pretty much anywhere you need to have
conditions and have different results by them.

91
8-13. Constraints

SQL constraints are the rules enforced on the data in a table. And the only data that meets
predetermined condition(s) is allowed to enter in order to ensure the integrity and reliability
of the data.

You specify constraints, in principle, at the time you create a table, but they can be modified
by using 'MODIFY COLUMN' or 'CHANGE (COLUMN)' whenever it needs to be
changed. You can give constraints on a table-wide basis as well as on a column. The
following are the most commonly used constraints:

Constraint Description

NULL Allows a column to have a 'NULL' value.

NOT NULL Ensures that a column cannot have a 'NULL' value.

DEFAULT Sets a default value for a column when no value is given.

UNIQUE Ensures that all values in a column are different.

Allows only a positive number to get in when the data is


UNSIGNED
numeric.

PRIMARY KEY Sets an identifier uniquely indicating a record in a table.

FOREIGN KEY Sets an identifier uniquely indicating a record in another table.

Sets an index to search and retrieve data more quickly from


INDEX
a table.

92
CHECK Ensures that the data meets the given condition(s).

Sets a unique number, which increases automatically each


AUTO_INCREMENT time a new record is added. If not specified, it starts with
'1' and increases '1' as an integer value.

Each column may have as many constraints as necessary, which followed after the
declaration of a data-type. However, 'PRIMARY KEY,' 'FOREIGN KEY,' 'UNIQUE,' and
'CHECK' conventionally make separate declarations.

create table constraints_demo


(
id int auto_increment,
nick_name varchar (20) not null,
age int unsigned not null,
address varchar(255) default 'New York',

primary key (id),


unique (nick_name),
check(age >= 18)
);

Now you may insert some data into the newly created table.

insert into constraints_demo(nick_name, age)


values ('Superman', 31),
('Batman', 32),
('Spiderman', 17);

The above statement will cause an error. The third data, Spiderman, is 17 years old, and it is
not satisfied with the condition set in 'CHECK,' which requires all data in the 'age' column

93
to be greater than 18. If you modify it as follows, however, you can enter the data with no
problem.

insert into constraints_demo(nick_name, age)


values ('Superman', 31),
('Batman', 32),
('Spiderman', 27);

select * from constraints_demo;

Don't miss out that no errors occurred even though you didn't present any data for the
columns of 'id' and 'address' in the above statement. It was possible because 'id' had a
constraint of 'auto_increment,' and 'address' had its own 'default' value.

As in the figure above, you can see a 'red key' on top of the nick_name column declared as
'UNIQUE.' If you use HeidiSQL, it automatically attaches a key-shaped icon on the
column that has a special meaning, and the color of the key shows its role.

94
8-14. FOREIGN KEY

Like 'PRIMARY KEY (PK),' 'FOREIGN KEY (FK)' plays a crucial role in DB
management. While running DB, it is typical to make and use multiple tables. And each of
the tables may operate independently but sometimes also refer to each other. For this
purpose, you need FKs. A FK is a special field in a table that refers to a PK in another table.
By using this, the integrity of data between tables can be ensured, and links between tables
can be prevented from collapsing.

FK obeys the rules as follows:

1. The table where a FK is declared is called a child table.


2. The table referenced from a child table is called a parent table.
3. Both parent and child tables must be InnoDB.
4. The parent table must exist before it is referenced.
5. The child table can only have values that exist in the referenced column in the parent
table.
6. The parent table connected by FK is not deletable.
7. The column of the parent table must be specified by the 'REFERENCE' keyword.
8. The column referenced by a child table must be designated as PK or UNIQUE.
9. The name of the column designated as FK and the name of the referenced column in
the parent table may be different. (but, it is common to match)
10. The character sets used by both the parent and the child table must match.
11. The data types of the referenced column in the parent table and those of the FK
column must match.
12. Columns with a data type of 'BLOB' or 'TEXT' cannot be designated as FK.
13. FK can be created at the time of defining a table or after a table defined, with the
'ALTER' command.

8-14-1. Creating Foreign Key

To create a FK, you insert the following query at the time of defining a child table.

95
CONSTRAINT <name of FK>
FOREIGN KEY (name of column in child table)
REFERENCES <name of parent table> (name of column in parent table)

/* defining a parent table */


create table parent
(
region_id int not null,
region varchar (10) not null,
primary key (region_id)
) engine = innodb default character set=utf8;

/* inserting data into the parent table */


insert into parent (region_id, region)
values (1, 'Jersey'), (2, 'Miami'), (3, 'New York');

/* defining a child table */


create table child
(
cid int not null auto_increment,
region_id int not null,
employee varchar (40) not null,
primary key (cid),
constraint fk_region foreign key (region_id) references parent (region_id)
) engine = InnoDB default character set=utf8;

As you can see above, we designated 'region_id' as a FK in the child table and made it
referenced by 'region_id' in the parent table using the 'REFERENCES' keyword. So now, you
cannot eliminate the parent table unless a child table is deleted first, and the number other than
1, 2, or 3, which was defined in the parent table, cannot be stored in the child table.

drop table parent;

96
The above error was caused by an attempt to remove a parent table without deleting its child
table. And the following query, which inserts data '4' that does not exist in the parent table
into the child table, also results in an error.

insert into child (region_id, employee)


values (1, 'James Moon'),
(2, 'Amelia Adams'),
(3, 'Clara Jackson'),
(4, 'Greg Hart');

However, there will be no problem if you switch the regional code 4 to the code existing in the
parent table, such as 1, 2, or 3.

97
insert into child (region_id, employee)
values (1, 'James Moon'),
(2, 'Amelia Adams'),
(3, 'Clara Jackson'),
(3, 'Greg Hart');

select * from child;

Like this, making a top-down relationship between tables using FK prevents unwanted data
from being entered and ensures data integrity.

8-14-2. Deleting Foreign Key

When you need to delete FK, you use the query 'ALTER TABLE' with the 'DROP' keyword.

ALTER TABLE <name of table>


DROP CONSTRAINT <name of FK>;

alter table child


drop constraint fk_region;

98
8-14-3. Adding Foreign Key

Even after defining a table, you may add 'FK' if necessary. In this case, you use the query
'ALTER TABLE' with the 'ADD' keyword.

ALTER TABLE <name of table>


ADD CONSTRAINT <name of FK>
FOREIGN KEY (name of column in child table)
REFERENCES <name of the parent table> (name of column in parent table)

alter table child


add constraint fk_region
foreign key (region_id)
references parent (region_id);

Just as there could be multiple primary keys in a table, foreign keys can also be created and
used as many as needed.

〔 DB Terms 9 〕 InnoDB vs. MyISAM

'InnoDB' is a DB engine for MySQL developed to make up for the shortcomings of


another DB engine, 'MyISAM.' The relatively simple structure of MyISAM has the
advantage of having a shorter time to process some queries, such as SELECT. Still,
MyISAM does not guarantee the integrity of the data, but InnoDB improves it. What's
more, InnoDB uses a row-by-row lock, unlike MyISAM using a table-by-table lock, so the
processing speed for many queries (INSERT, UPDATE, DELETE, and so forth) is faster
than MyISAM.

99
8-15. INDEX

The statement 'CREATE INDEX' is used to create an index on a table. The column
designated as an index is faster for searching data. However, if a table has an index, you
should note that more time is needed when updating it. Therefore, you'd better have only
the number of indexes you undoubtedly need.

8-15-1. Creating Index

CREATE INDEX <name of index>


ON <name of table> (desired column);

create index idx_name


on employees_miami (first_name);

select * from employees_miami;

Just as putting 'fk_' before the name of a foreign key, it is custom to put 'idx_' before the
name of an index.

Like above, the indexed column has the key icon colored green if you use HeidiSQL.

100
8-15-2. Deleting Index

When you need to delete an index, you use the query 'ALTER TABLE' with the 'DROP'
keyword.

ALTER TABLE <name of table>


DROP INDEX <name of index>;

alter table employees_miami


drop index idx_name;

8-16. Stored Procedure

One of the powerful features offered by SQL, STORED PROCEDURE, is a macro or a


function saving the codes that you write and use over and over. You can save repeated SQL
queries under a separate name and reuse them like a single small program. It is advantageous
due to the nature of DB management, which has a lot of repetitive tasks. 'STORED
PROCEDURE' is saved in the form of a user-defined function, so you must put parentheses
after the name of it.

8-16-1. Creating Stored Procedure

CREATE PROCEDURE <name of procedure>( )


<desired queries>;

create procedure average_salary()


select format(avg(salary), 2) from employees_miami;

Now you can re-use the procedure any time you want by typing in as follows:

101
CALL <name of procedure>( );

call average_salary();

However, you may wonder if you really need a stored procedure for these simple queries.
And your question is legitimate because the reason for the existence of 'STORED
PROCEDURE' may be to make repetitive long and complicate DB queries simple and easy.

To achieve this, you need to use a little different syntax rule as follows:

DELIMITER <symbol character(s)>


CREATE PROCEDURE <name of procedure>( )
BEGIN
<desired queries>;
END <symbol character(s)>

In SQL, a semicolon, called a 'delimiter,' means the end of a query. Thus, it is necessary to
treat semicolons differently to place multiple queries in a single procedure. To that end, you
insert 'DELIMITER $$' in the first line, which declares '$$' as a new delimiter. Now,
semicolons inside the code block, produced by the keywords 'BEGIN' and 'END,' will be
ignored, and '$$' after the 'END' will make the end of the statement.

You may use other characters like '//' or '##' as a new delimiter as long as it is not one of
the reserved words in SQL.

102
The statement below will show the data of all the employees from 'Jersey' and 'Miami.' To do
so, it creates a temporary table called 'employees_all' to receive all the data from two
branches. After that, the temporary table will be deleted so that you can use it over and over
again.

delimiter $$
create procedure show_all_employees()
begin

create temporary table employees_all


(
aid int auto_increment,
first_name varchar(20),
last_name varchar(20),
department varchar(20),
salary int,
gender varchar(6),
age int,
joined_date date,
branch varchar(10),
primary key (aid)
);

insert into employees_all (first_name, last_name, department, salary, gender, age,


joined_date, branch)
select first_name, last_name, department, salary, gender, age, joined_date, 'Jersey'
from employees_jersey;

insert into employees_all (first_name, last_name, department, salary, gender, age,


joined_date, branch)
select first_name, last_name, department, salary, gender, age, joined_date, 'Miami'
from employees_miami;

103
select * from employees_all;

drop table employees_all;

end $$

8-16-2. Deleting Stored Procedure

Use the 'DROP' keyword when you want to delete a stored procedure. Please note that you
don't need to attach parentheses after the name of the stored procedure.

DROP PROCEDURE <name of procedure>;

drop procedure show_all_employees;

104
9. User Account Management

DB operations may require multiple administrators who have full authorities and multiple
users who have only limited controls on DB. It is very inappropriate for all of the users to
share a single administrator account. Therefore, you must be able to register new users and
limit their access to DBs.

9-1. Creating New User

CREATE USER '<user name>'@'localhost' IDENTIFIED BY '<user passoword>';

Let's execute the query below. We will add a new user named 'hello,' and set the password as
'hellowworld.' If you want, you can have your own password as you wish.

create user 'hello'@'localhost' identified by 'helloworld';

In the above statement, we wrote 'localhost' after the user name, which means we allow the
user to access a DB server only thru the local connection. If you want to permit remote
access to a user, you should write 'hello'@'%.' And if you wish to allow access only from a
specific location, you specify the IP address like '192.168.*.*'. You should remember that
every access point is considered a different account, even for the same user. That means, if
you allow a user to have access from local and remote, you should create both accounts
separately.

There are many single quotes in the queries to manage users, and you cannot omit them.

9-2. Setting Privileges

105
To allow a new user to access your DB, you must first give authority to that user. The
keyword for this is 'GRANT.'

GRANT <allowed_query_1, allowed_query_2, ..., allowed_query_n>


ON <allowed_DB> TO '<user_name>'@'<access_point>';

grant select, insert, update, delete, create, drop, alter on mysql.* to 'hello'@'localhost';

You can specify permitted queries one by one to individual users or grant permission for all
the query words at once. Write 'grant all privileges' if you want to give full authority to a
user. And you may grant authority over all tables in the DB by putting '*' after the DB name
(mydb.*). Still, if you want to give the user access to only specific tables, you specify the table
name(s) (mydb.employees_miami). If what you want is to provide full authority on all the
DBs and the tables, you write '*.*' in your query statement.

e.g., mysql.event : only event table in mysql database is permitted


mysql.* : All tables in mysql database are permitted
*.* : All tables in all databases are permitted

grant all privileges on *.* to 'hello'@'localhost';

9-3. Revoking Privileges

You may restrict or reclaim permissions on queries just like you can grant them to users. If
you want to revoke the given authorities, do as follows:

REVOKE <restricted_query_1, restricted_query_2, ..., restricted_query_n>


ON <restricted_DB> FROM '<user_name>'@'<access_point>';

revoke all privileges on *.* from 'hello'@'localhost';

106
The above statement is to revoke all the given authorities from the user 'hello.' If you want
to withdraw only some of the permissions, not all of them, you can list the queries you wish
with commas, instead of writing 'all privileges.' The statement below will revoke three
queries from the user: create, drop, and delete.

revoke create, drop, delete on *.* from 'hello'@'localhost';

9-4. Deleting User

There must be the case that you need to delete a user account rather than just reclaiming
their authorities. If you wish to drop a registered user, you will use the query 'DROP USER'
as follows:

DROP USER '<user_name>'@'<access_point>';

drop user 'hello'@'localhost';

The statement above will drop the user account, 'hello,' who has access via the local
connection.

107
10. Backup and Restore

As the primary purpose of operating DB is to store data, it is only natural that you should be
able to back up and restore data. You can back up the entire DB or only a part of it.
However, end-users do not have permission to do it, and only the 'root' user can perform
the backup function.

Even fully authorized users cannot back up or restore DB. The permission to do it is
granted only to the root user.

The backup and restore functions are not the queries in SQL. Therefore, they do not work
within a SQL management program, such as HeidiSQL. You must run them on the
command prompt provided by the OS: Windows in your case.

Let's move to the folder in which MariaDB you installed, using the command prompt;
MariaDB is initially installed under the folder, 'C:\Program Files,' with the name of
'MariaDB xx.xx.' Entering the folder, you will see the folder named 'bin.' To back up or
restore DB, you carry out the task in this folder with the following command:

MYSQLDUMP –u<root user> -p<password> <backup type> > <location and name for backup>

To carry out the performance properly, you should run 'command prompt' in 'Run as
administrator' mode; otherwise, you won't be able to use backup and restore functionalities.

When MariaDB is installed, it provides two backup tools by default: mariabackup and
mysqldump. The reason for using 'mysqldump' in this book is that it gives more flexible
and faster backup and restore functionalities. Besides, 'mysqldump' also supports backups
into CSV or XML formats, making it easy to get imported into another type of DB server.
However, there could be a downside too; when the size of data is too big, 'mysqldump'
may function slower than 'mariabackup.'

108
10-1. Full Backup

mysqldump –u root –p –A > c:\maria_backup.sql

In the above statement, '–A' means all databases. You may enter your password after '-p,' but
you can also leave it blank and enter your password later separately.

If no error message appears, it means that the backup process is completed successfully.

There are two command options for backup of all DBs: '–A' and '--all-databases,' which
have the same function and result.

10-2. Partial Backup

You know that there can be multiple DBs in a DB server. If you want to back up only the
specific DBs among the many DBs that exist on the server, just present the DB name(s) you
need to backup, instead of '-A' as follows:

mysqldump –u root –p mydb > c:\mydb_backup.sql

109
To back up not one DB but multiple DBs on a server at once, list the names of the DBs as
follows: However, you don't use a comma like in typical SQL queries.

MYSQLDUMP –u<root user> -p<password> —databases <db names> > <location and name for backup>

mysqldump –u root –p --databases mydb mysql > c:\mydb_mysql_backup.sql

10-3. Table Backup

Not only can you back up specific DBs, but you can back up only particular tables within a
particular DB. To do so, just present the name of the desired table after the DB name as
follows:

MYSQLDUMP –u root –p <db name> <table name> > <location and name for the backup>

mysqldump –u root –p mydb promotion > c:\mydb_promotion.sql

Executing the above command will only back up the 'promotion' tables among the tables in
the 'mydb' database.

110
10-4. Backup without Data

You can back up only the structure of the DB, so-called schema, without its data. The
option used for this is '--no-data,' and the DB name should be presented after this option.

10-4-1. Backup All Schema

mysqldump –u root –p --no-data –A > c:\alldb_schema_only.sql

The above statement will only back up the schema of all DBs on the server, excluding data.

10-4-2. Backup Specific Schema

mysqldump –u root –p --no-data mydb > c:\mydb_schema_only.sql

The above statement will only back up the schema of the database 'mydb,' excluding its data.

〔 DB Terms 10 〕 What is 'Schema'?

'Schema' is a general description of the structure and constraints of the database. It


describes what structure data is stored in the DB and expresses the relationship between
logical units of data within the DB, categorized by external, internal, and concept schema
based on user perspective.

111
10-5. Scheduled Backup

It is essential to back up DBs periodically in case of contingencies. Unfortunately, it is not


easy to find this feature in free DB management tools. Therefore, it is recommended to
create a batch file(.bat) and used it with 'Task Scheduler' provided by Windows.

STEP.1 Open any text editor, write the following, and save it as a batch file.

ECHO MariaDB Database Scheduled Backup


mysqldump -u root –p <root password> -A > <backup file location>\Backup_%date%.sql

ECHO Delete the file(s) passed more than 30 days


forfiles /P <backup file location> /S /M *.sql /D -90 /C "cmd /c del @file"

The above DOS command not just automatically backs up databases but also sequentially
deletes the files passed more than 90 days. If you want to change the interval of removal,
modify the part that says '–90' after '/D' to what-date-ever you wish: The acceptable range is
from 0 to 32768 days.

It is mandatory to present the root password when you make a batch file, but you can
choose your backup files' saving location according to your needs. Then you should place
your batch file in the same folder in which the 'mysqldump' program exists (C:\Program
Files\MariaDB xx.xx\bin\).

STEP.2 Registering within task scheduler

Using the search function provided by Windows, find and run 'Task Scheduler,' and you
will see the screen below, where you can select 'Create Basic Task...' on the right upper
side, and there you enter the name and choose cycle of backup in the dialog box that
appears. In the final step, you select the batch file you created earlier.

112
113
114
115
In this box, choose the batch file you created earlier. Clicking the <Next> button will
complete the registration of the schedule, and from then on, it will automatically back up
your database at the time you set.

10-7. Restoring Backup

To restore your backups, you use the following command:

MYSQL –u root –p <db name> < <location and name of the backup>

mysql –u root –p mydb < c:\mydb_backup.sql

And if you want to restore all your DBs, you can do it with the same option(s) you used to
back them up.

mysql –u root –p –A < c:\maria_backup.sql

When using the above command, remember two things:

1. Use the command 'mysql' instead of 'mysqldump.'


2. Use '<' which is the opposite direction to '>' in front of the name of your backup file.

116
11. Data Types in MariaDB

The types of data that MariaDB allows are so broad that it is difficult to explain all of them,
so here I will introduce only the most frequently used ones.

11-1. String Data Types

Data Type Description

A fixed-length string (may include letters, numbers, and special


characters). Size means the maximum number of characters it can
CHAR(size)
hold: maximum of 255 characters. The default value of the size is
1 when you do not specify the value.

A variable-length string (may include letters, numbers, and special


VARCHAR(size) characters). Size means the maximum number of characters it can
hold: maximum of 65,535 characters.

Store up to 255 characters. However, if you use multi-byte characters


TINYTEXT
like Korean, Chinese, etc., it may hold up to 85 characters.

Store up to 65,535 characters. However, if you use multi-byte


TEXT(size) characters like Korean, Chinese, etc., it may hold up to 21,845
characters.

Store up to 16,777,215 characters. However, if you use multi-byte


MEDIUMTEXT characters like Korean, Chinese, etc., it may hold up to 5,592,405
characters.

Store up to 4,294,967,295 characters. However, if you use multi-byte


LONGTEXT characters like Korean, Chinese, etc., it may hold up to 1,431,655,765
characters.

117
11-2. Numeric Data Types

Data Type Description

A very small integer: the signed range is from –128 to 127,


TINYINT
and the unsigned from 0 to 255.

A small integer: the signed range is from –32,768 to 32,767,


SMALLINT
and the unsigned from 0 to 65,535 without a sign.

A medium-sized integer: the signed range is from –8,388,608


MEDIUMINT
to 8,388,607, and the unsigned from 0 to 16,777,215.

A normal-sized integer: the signed range is from –2,147,486,348


INT
to 2,147,483,647, and the unsigned from 0 to 4,294,967,295.

A small floating-point number (single-precision): the total number


FLOAT(size, d) of digits is specified by (size), and the number of digits after the
decimal point is determined by (d).

A normal-sized floating-point number (double-precision): the total


DOUBLE(size, d) number of digits is specified by (size), and the number of digits
after the decimal point is determined by (d).

An exact fixed-point number: the total number of digits is


specified by (size), and the number of digits after the decimal point
DECIMAL(size, d)
is determined by (d). The maximum value that (size) can have is
65, and the maximum value that (d) can have is 30.

A bit-field data type allowed from 1 bit to 64 bit: The default value
BIT(size)
is '1' if (size) is omitted, often used for a boolean type.

118
11-3. Date and Time Data Types

Data Type Description

A date displaying in the form of 'YYYY-MM-DD': the range is


DATE
from '1000-01-01' to '9999-12-31'

A time displaying in the form of 'hh:mm:ss': the range is from


TIME
'-838:59:59' to '838:59:59'

A year displaying in the form of XXXX': the range is from '1901' to


YEAR '2155' in four-digit format, and '70' to '69' representing years from
1970 to 2069.

A date and a time combination displaying in the form of 'YYYY-MM-


DATETIME DD hh:mm:ss': the range is from '1000-01-01 00:00:00' to '9999-12-31
23:59:59'

A timestamp displaying in the form of 'YYYY-MM-DD hh:mm:ss':


the range is from '1970-01-01 00:00:01' UTC to '2038-01-09 03:14:07'
TIMESTAMP UTC. When defining a column, giving the option 'DEFAULT
CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'
will automatically update the date and time up to date.

119
11-4. Binary Data Types

Data Type Description

A binary type data: similar to CHAR type, but stores data in


BINARY(size) the form of binary. Size also means not the number of characters
but the length in bytes it can hold.

A binary type data: similar to VARCHAR type, but stores data in


VARBINARY(size) the form of binary. Size also means not the number of characters
but the length in bytes it can hold.

TINYBLOB A binary type data with a maximum length of 255 bytes.

A binary type data with a maximum length of 65,535 bytes: If the


BLOB(size) size is given, it creates the column large enough to hold (size) bytes
long.

A binary type data with a maximum length of 16,777,215 bytes,


MEDIUMBLOB
which is the same as 16MB in size.

A binary type data with a maximum length of 4,294,967,295 bytes,


LONGBLOB
which is the same as 4GB in size.

〔 DB Terms 11 〕

'BLOB' is an abbreviation for Binary Large Object, commonly used in dealing with
multimedia data such as images, sounds, videos, etc.

120
11-6. Other Data Types

Data Type Description

A set of string objects: The usable values must be predefined


in the list, and the list can have from 0 to a maximum of 64
values. It is distinguished from 'ENUM' where it can select a
SET (value_1, value_2, ...) value or multiple values at the same time.

e.g., SET(TV, chat, dinner)


: we can have dinner, chatting and watching TV together.

A sequential set of string objects: The usable values must be


predefined in the list, and the list can have 1 to 65,535
distinct values. It is distinguished from 'SET' where it cannot
ENUM(value_1, value_2, ...) select zero value or multiple values at the same time.

e.g., EUM(breakfast, lunch, dinner)


: we cannot have breakfast and lunch at the same time.

121
122
James Moon

Studied at San Jose State University, majored in Computer Science, and worked as a software
developer in the Silicon Valley area for 7 years. Returning to his home country South Korea,
developing educational statistics program since then.

123

You might also like