0% found this document useful (0 votes)
27 views

Mysql Course

Uploaded by

cnin
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
27 views

Mysql Course

Uploaded by

cnin
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 223

Getting Started with Databases

Show Me The Data!

Imagine this:

Your favorite news site with no articles


• where'd all my news go?!?
Your online banking portal showing a (faulty) zero balance
• where'd all my money go?!?
Facebook and Instagram with zero pictures or posts
• where'd all my friends go?!?
Netflix without a single movie on it
• Where my shows at?!?

If it weren't for databases, all those circumstances above (and many, many
other similar situations) would be our digital reality. Fortunately, we have
these things called "databases" which are basically just pieces of really
advanced software designed solely and specifically for the purpose of storing
our data in a clear and concise way - allowing us to query said data at our
leisure.

In software development, we call the act of saving data to a database and


working with a database "data persistence". Meaning, we would like our
application’s data to outlive the applications process. In Java terms, we would
like the state of (some of) our objects to live beyond the scope of the JVM so
that the same state is available later.

Conceptually, databases are quite similar to a collection of Excel


spreadsheets. Database tables are, to oversimplify it, just a collection of
columns (fields) and rows (data) as you can see in the image below.
That said, databases are significantly more useful and powerful than a simple
collection of spreadsheets. What makes databases so useful is the ability to
run complex queries against these data sets to extract the exact data we
need without having to scroll or iterate through thousands or millions or
billions of records.

So Many Databases, So Little Time


There are dozens of database providers out there these days. Here are a few
of the most common and popular database technologies today:

• MySQL (which we'll be using)


◦ Open-source, hugely popular, relational
• PostgreSQL (which we'll also introduce)
◦ Open-source, hugely popular, relational
• Oracle
◦ Super-corporate, designed for enterprise customers, open-
source, relational
• Microsoft SQL Server (kind of like a closed-source version of MySQL
◦ Basically Microsoft's closed-source version of MySQL
• Mongo DB
◦ Document-oriented, NoSQL, open-source
• IBM
◦ Db2 is a family of hybrid data management products designed to
help you manage both structured and unstructured data
• Redis
◦ key-value store, in-memory data structure, used as a database,
cache and message broker
• Cassandra
◦ Originally built by Facebook for massive data sets, then open-
sourced
• And another roughly 335 DB technologies with decreasing uses and
popularities

As previously mentioned, in this course we'll be using MySQL, which is one of


the most popular, industry-leading relational database technologies on the
market. It also happens to be open-source and free, which is quite nice :)

In the coming sections, we'll dive into using the MySQL database as we'll
introduce PostgreSQL. So, let's get started!
SQL vs MySQL
A very common question as people get started with databases is, "what's
the difference between SQL and MySQL?" The answer is quite simple.

SQL is a language, a query language.

MySQL, PostGre, SQL Server, and all the others are the database
engines (software applications) that store the data and execute the
SQL queries.

Structured Query Language (SQL)

SQL (pronounced "ess-que-el" or "sequel", depending on whom you ask)


stands for Structured Query Language. SQL is a standard language for
accessing databases. SQL has been an international standard (ISO) since
1987. Structured Query Language (SQL) is a standard computer language
for relational database management and data manipulation. SQL is used to
query, insert, update and modify data. SQL is defined by the ANSI/ISO SQL
Standard. All modern relational database management systems (RDBMS) -
such as MySQL, support SQL.

SQL is used to communicate with a database. According to ANSI (American


National Standards Institute), it is the standard language for relational
database management systems. SQL statements are used to perform tasks
such as update data on a database (ie, a MySQL database), or retrieve data
from a database. Some common relational database management systems
that use SQL are: MySQL, PostgreSQL, Oracle, Microsoft SQL Server etc.
Although most database systems use SQL, most of them also have their own
additional proprietary extensions. However, the standard SQL commands
such as "Select", "Insert", "Update", "Delete", "Create", and "Drop" can be
used to accomplish almost everything that one needs to do with a database.
(link)
MySQL

MySQL, PostgreSQL, Oracle, Microsoft SQL Server, and all the others just
independent database technologies. Fortunately, they all support ANSI SQL
- so once you know one of them, you kind of know all of them. They all have
some unique traits, but the commonalities between them far outweigh the
differences.

MySQL, like the others in its class, is a database management system. A


database is a structured collection of data. It may be anything from a simple
shopping list to a picture gallery or the vast amounts of information in a
corporate network. To add, access, and process data stored in a computer
database, you need a database management system such as MySQL Server.
Since computers are very good at handling large amounts of data, database
management systems play a central role in computing, as standalone
utilities, or as parts of other applications. (link)

MySQL databases are relational.

A relational database stores data in separate tables rather than putting


all the data in one big storeroom. The database structures are organized
into physical files optimized for speed. The logical model, with objects
such as databases, tables, views, rows, and columns, offers a flexible
programming environment. You set up rules governing the relationships
between different data fields, such as one-to-one, one-to-many,
unique, required or optional, and “pointers” between different tables.
The database enforces these rules, so that with a well-designed
database, your application never sees inconsistent, duplicate, orphan,
out-of-date, or missing data.

The SQL part of “MySQL” stands for “Structured Query Language”. SQL
is the most common standardized language used to access databases.
Depending on your programming environment, you might enter SQL
directly (for example, to generate reports), embed SQL statements into
code written in another language, or use a language-specific API that
hides the SQL syntax.

SQL is defined by the ANSI/ISO SQL Standard. The SQL standard has
been evolving since 1986 and several versions exist. In this
manual, “SQL-92” refers to the standard released in
1992, “SQL:1999” refers to the standard released in 1999,
and “SQL:2003” refers to the current version of the standard. We use
the phrase “the SQL standard” to mean the current version of the SQL
Standard at any time.

MySQL software is Open Source.

Open Source means that it is possible for anyone to use and modify the
software. Anybody can download the MySQL software from the Internet
and use it without paying anything. If you wish, you may study the
source code and change it to suit your needs. The MySQL software
uses the GPL (GNU General Public
License), http://www.fsf.org/licenses/, to define what you may and may
not do with the software in different situations. If you feel uncomfortable
with the GPL or need to embed MySQL code into a commercial
application, you can buy a commercially licensed version from Oracle.

The MySQL Database Server is very fast, reliable, scalable, and


easy to use.

If that is what you are looking for, you should give it a try. MySQL Server
can run comfortably on a desktop or laptop, alongside your other
applications, web servers, and so on, requiring little or no attention. If
you dedicate an entire machine to MySQL, you can adjust the settings
to take advantage of all the memory, CPU power, and I/O capacity
available. MySQL can also scale up to clusters of machines, networked
together.
MySQL Server was originally developed to handle large databases
much faster than existing solutions and has been successfully used in
highly demanding production environments for several years. Although
under constant development, MySQL Server today offers a rich and
useful set of functions. Its connectivity, speed, and security make
MySQL Server highly suited for accessing databases on the Internet.

MySQL Server works in client/server or embedded systems.

The MySQL Database Software is a client/server system that consists of


a multithreaded SQL server that supports different back ends, several
different client programs and libraries, administrative tools, and a wide
range of application programming interfaces (APIs).

We also provide MySQL Server as an embedded multithreaded library


that you can link into your application to get a smaller, faster, easier-to-
manage standalone product.

A large amount of contributed MySQL software is available.

MySQL Server has a practical set of features developed in close


cooperation with our users. It is very likely that your favorite application
or language supports the MySQL Database Server.
Installing MySQL
Please follow the directions here for specific instructions on installing MySQL
on your system.

IMPORTANT! Write down the (strong) password you set when you are
installing MySQL!

This password needs to be strong, and you'll need it again and again as you
move forward. So please take a moment to create a strong password and
make sure that you write in down and/or save it to a known location on your
machine.

Testing Installation

After completing the MySQL installation on your machine, please run the
following commands from the CLI to start MySQL (if it's not started already)
and verify it's installation:

On Mac:

1. On a Mac you can quickly and easily start and stop MySQL in the
System Preferences:
2. If you'd prefer to start MySQL from the CLI you can run:
sudo /usr/local/mysql/support-files/mysql.server start
1. Please note that if MySQL is already running, this will throw an
error.
3. If the command above does not work try this one: sudo launchctl load
-F /Library/LaunchDaemons/com.oracle.oss.mysql.mysqld.plist
4. mysql --version

On Linux

/etc/init.d/mysqld start
/etc/init.d/mysqld stop
/etc/init.d/mysqld restart

Some Linux flavors offer the service command too

service mysqld start


service mysqld stop
service mysqld restart

or

service mysql start


service mysql stop
service mysql restart

On Windows

C:\> "C:\Program Files\MySQL\MySQL Server 8.0\bin\mysqld"


C:\> "C:\Program Files\MySQL\MySQL Server 8.0\bin\mysqladmin" -u
root shutdown

After running the appropriate command above for your system, you should
see a nice message printed out that tells you the version of MySQL that is
now installed on your system. For instance, try running the command mysql
--version from the CLI. (Your version number will vary.)

Adding MySQL to the System PATH

If you're trying to run the "mysql" command but you're receiving the error
message "'mysql' is not recognized as an internal or external command" this
means that the MySQL "bin" directory was not added to the system PATH
variable. The PATH variable contains a list of directories where you're
operating system can search for the "MySQL" command.

To add MySQL to your PATH click here for simple instructions for Mac or
Linux, for PC users please follow the directions below (source):

1. On the Windows desktop, right-click My Computer.


2. In the pop-up menu, click Properties.
3. In the System Properties window, click the Advanced tab, and then
click Environment Variables.
4. In the System Variables window, highlight Path, and click Edit.
5. In the Edit System Variables window, insert the cursor at the end of
the Variable value field.
6. If the last character is not a semi-colon (;), add one.
7. After the final semi-colon, type the full path to the "bin" directory within
the MySQL installation on your machine. This will look something like
"C:\Program Files\MySQL\MySQL Server 5.6\bin". (You may also
have the option to add this as a new entry in a table of entries.)
8. Click "save" or "ok"
9. Restart your terminal emulator or command prompt
10. Test the "mysql" command using "mysql --version". You should now
see the version print out, meaning the installation is good to go.
Installing & Connecting to MySQL
Workbench
MySQL Workbench is a Graphical User Interface (GUI) for interacting with
MySQL databases. (We can and do often interact with MySQL from the CLI -
but MySQL Workbench is far more useful and productive for working with
and managing real-world databases.)

Please follow the installation instructions here for your specific machine.

After installing MySQL Workbench, please launch the application and click
the "+" icon to create a new connection.

Then configure the connection to match the image below:


Lastly, click "Store in Keychain" and type in your MySQL (strong) password
that you created and saved earlier when we installed MySQL. Once you have
entered your password click "OK". Then, click "Test Connection". (If MySQL
is not running, this test will fail. So be sure MySQL is currently running on
your machine.) The test should pass. Once the test has passed, click "OK"
on the screen from the image above. This should open a screen that
resembles the following image.

If you do not see a screen resembling the image above, and instead you see
a screen resembling the image below - that means you need to start MySQL
Server. In this case, quit MySQL Workbench, start MySQL (refer to the
previous page for instructions) then relaunch MySQL Workbench.
Understanding Relational Databases
A relational database is a collection of data items with pre-defined
relationships between them. These items are organized as a set of tables
with columns and rows. Tables are used to hold information about the
objects to be represented in the database. Each column in a table holds a
certain kind of data and a field stores the actual value of an attribute. The
rows in the table represent a collection of related values of one object or
entity. Each row in a table could be marked with a unique identifier called a
primary key, and rows among multiple tables can be made related using
foreign keys. This data can be accessed in many different ways without
reorganizing the database tables themselves. (link)

Notice in the image below how each table only contains data about that
element. For instance, the Passenger table only contains information directly
related to the passenger. The flight table only contains information about the
flight. The Payment table only contains information about the payments, and
so on. That said, we can connect/relate these tables to each using keys.
Using this design we are able to keep our database clean, concise and
scalable.
The content below is sourced from https://www.ntu.edu.sg

Introduction

The relational database was proposed by Edgar Codd (of IBM Research)
around 1969. It has since become the dominant database model for
commercial applications. Today, there are many commercial Relational
Database Management System (RDBMS), such as Oracle, IBM DB2 and
Microsoft SQL Server. There are also many free and open-source RDBMS,
such as MySQL, mSQL (mini-SQL) and the embedded JavaDB (Apache
Derby).

A relational database organizes data in tables (or relations). A table is made


up of rows and columns. A row is also called a record (or tuple). A column is
also called a field (or attribute). A database table is similar to a spreadsheet.
However, the relationships that can be created among the tables enable a
relational database to efficiently store huge amount of data and effectively
retrieve selected data.

SQL (Structured Query Language) was developed to work with relational


databases.

Database Design Objective

A well-designed database shall:

Eliminate data redundancy: the same piece of data shall not be


stored in more than one place. This is because duplicate data not
only waste storage spaces but also easily lead to inconsistencies.
Ensure data integrity and accuracy.
Provide access with information a user needs to join tables
together.

Relational Database Design Process

Database design is more art than science, as you have to make many
decisions. Databases are usually customized to suit a particular application.
No two customized applications are alike, and hence, no two databases are
alike. Guidelines (usually in terms of what not to do instead of what to do)
are provided in making these design decision, but the choices ultimately rest
on you - the designer.

Step 1: Define the Purpose of the Database (Requirement Analysis)

Gather the requirements and define the objective of your database.

Step 2: Gather Data, Organize in tables and Specify the Primary Keys

Once you have decided on the purpose of the database, gather the data that
are needed to be stored in the database. Divide the data into subject-based
tables.
Choose one column (or a few columns) as the so-called primary key, which
uniquely identifies each of the rows.

Primary Key

In the relational model, a table cannot contain duplicate rows, because that
would create ambiguities in retrieval. To ensure uniqueness, each table
should have a column (or a set of columns), called primary key, that uniquely
identifies every record of the table. For example, a unique
number customerID can be used as the primary key for
the Customers table; productCode for Products table; isbn for Books table. A
primary key is called a simple key if it is a single column; it is called
a composite key if it is made up of several columns.

Most RDBMSs build an index on the primary key to facilitate fast search and
retrieval.

The primary key is also used to reference other tables (to be elaborated
later).

You have to decide which column(s) is to be used for the primary key. The
decision may not be straight forward but the primary key shall have these
properties:

The values of the primary key shall be unique (i.e., no duplicate


value). For example, customerName may not be appropriate to be
used as the primary key for the Customers table, as there could be
two customers with the same name.
The primary key shall always have a value. In other words, it shall
not contain NULL.

Consider the following when choose the primary key:

The primary key shall be simple and familiar,


e.g., employeeID for employees table and isbn for books table.
The value of the primary key should not change. A primary key is
used to reference other tables. If you change its value, you have to
change all its references; otherwise, the references will be lost. For
example, phoneNumber may not be appropriate to be used as the
primary key for table Customers, because it might change.
The primary key often uses integer (or number) type. But it could
also be other types, such as texts. However, it is best to use a
numeric column as the primary key for efficiency.
The primary key could take an arbitrary number. Most RDBMSs
support so-called auto-increment (or AutoNumber type) for integer
primary key, where (current maximum value + 1) is assigned to the
new record. This arbitrary number is fact-less, as it contains no
factual information. Unlike factual information such as phone
number, a fact-less number is ideal for the primary key, as it does
not change.
The primary key is usually a single column
(e.g., customerID or productCode). But it could also make up of
several columns. You should use as few columns as possible.

Let's illustrate with an example: a table customers contains


columns lastName, firstName, phoneNumber, address, city, state, zipCode.
The candidates for primary key are name=(lastName,
firstName), phoneNumber, Address1=(address, city, state), Address1=
(address, zipCode). Name may not be unique. Phone number and address
may change. Hence, it is better to create a fact-less auto-increment number,
say customerID, as the primary key.

Step 3: Create Relationships among Tables

A database consisting of independent and unrelated tables serves little


purpose (you may consider using a spreadsheet instead). The power of
relational database lies in the relationship that can be defined between
tables. The most crucial aspect in designing a relational database is to
identify the relationships among tables. The types of relationship include:

1. one-to-many
2. many-to-many
3. one-to-one

One-to-Many

In a "class roster" database, a teacher may teach zero or more classes, while
a class is taught by one (and only one) teacher. In a "company" database, a
manager manages zero or more employees, while an employee is managed
by one (and only one) manager. In a "product sales" database, a customer
may place many orders; while an order is placed by one particular customer.
This kind of relationship is known as one-to-many.

A one-to-many relationship cannot be represented in a single table. For


example, in a "class roster" database, we may begin with a table
called Teachers, which stores information about teachers (such
as name, office, phone and email). To store the classes taught by each
teacher, we could create columns class1, class2, class3, but faces a
problem immediately on how many columns to create. On the other hand, if
we begin with a table called Classes, which stores information about a class
(courseCode, dayOfWeek, timeStart and timeEnd); we could create additional
columns to store information about the (one) teacher (such
as name, office, phone and email). However, since a teacher may teach many
classes, its data would be duplicated in many rows in the table Classes.

To support a one-to-many relationship, we need to design two tables: a


table Classes to store information about the classes with classID as the
primary key; and a table Teachers to store information about teachers
with teacherID as the primary key. We can then create a one-to-many
relationship by storing the primary key of the table Teacher (i.e., teacherID)
(the "1"-end of the parent table) in the table classes (the "many"-end or
the child table), as illustrated below.

Source: ntu.edu.sg

The column teacherID in the child table Classes is known as the foreign key.
A foreign key of a child table is a primary key of a parent table, used to
reference the parent table.

Take note that for every value in the parent table, there could be zero, one, or
more rows in the child table. For every value in the child table, there is one
and only one row in the parent table.

Many-to-Many

In a "product sales" database, a customer's order may contain one or more


products; and a product can appear in many orders. In a "bookstore"
database, a book is written by one or more authors; while an author may
write zero or more books. This kind of relationship is known as many-to-
many.

Let's illustrate with a "product sales" database. We begin with two


tables: Products and Orders. The table products contains information about
the products (such as name, description and quantityInStock)
with productID as its primary key. The table orders contains customer's
orders (customerID, dateOrdered, dateRequired and status). Again, we
cannot store the items ordered inside the Orders table, as we do not know
how many columns to reserve for the items. We also cannot store the order
information in the Products table.

To support a many-to-many relationship, we need to create a third table


(known as a junction table), say OrderDetails (or OrderLines), where each
row represents an item of a particular order. For the OrderDetails table, the
primary key consists of two columns: orderID and productID, that uniquely
identify each row. The columns orderID and productID in
the OrderDetails table is used to reference Orders and Products tables,
hence, they are also the foreign keys in the OrderDetails table.

Source: ntu.edu.sg
The many-to-many relationship is, in fact, implemented as two one-to-many
relationships, with the introduction of the junction table.

1. An order has many items in OrderDetails. An OrderDetails item


belongs to one particular order.
2. A product may appear in many OrderDetails.
Each OrderDetails item specifies one product.

One-to-One

In a "product sales" database, a product may have optional supplementary


information such as image, moreDescription and comment. Keeping them
inside the Products table results in many empty spaces (in those records
without these optional data). Furthermore, these large data may degrade the
performance of the database.

Instead, we can create another table


(say ProductDetails, ProductLines or ProductExtras) to store the optional
data. A record will only be created for those products with optional data. The
two tables, Products and ProductDetails, exhibit a one-to-one relationship.
That is, for every row in the parent table, there is at most one row (possibly
zero) in the child table. The same column productID should be used as the
primary key for both tables.

Some databases limit the number of columns that can be created inside a
table. You could use a one-to-one relationship to split the data into two
tables. A one-to-one relationship is also useful for storing certain sensitive
data in a secure table, while the non-sensitive ones in the main table.
Source: ntu.edu.sg

Column Data Types

You need to choose an appropriate data type for each column. Commonly
data types include integers, floating-point numbers, string (or text),
date/time, binary, collection (such as enumeration and set).

Step 4: Refine & Normalize the Design

adding more columns,


create a new table for optional data using a one-to-one
relationship,
split a large table into two smaller tables,
others.

Normalization

Apply the so-called normalization rules to check whether your database is


structurally correct and optimal.

First Normal Form (1NF)

A table is 1NF if every cell contains a single value, not a list of values. This
property is known as atomic. 1NF also prohibits a repeating group of
columns such as item1, item2,.., itemN. Instead, you should create another
table using a one-to-many relationship.

Second Normal Form (2NF)

A table is 2NF, if it is 1NF and every non-key column is fully dependent on


the primary key. Furthermore, if the primary key is made up of several
columns, every non-key column shall depend on the entire set and not part
of it.

For example, the primary key of the OrderDetails table


comprising orderID and productID. If unitPrice is dependent only
on productID, it shall not be kept in the OrderDetails table (but in
the Products table). On the other hand, if the unitPrice is dependent on the
product as well as the particular order, then it shall be kept in
the OrderDetails table.

Third Normal Form (3NF)

A table is 3NF, if it is 2NF and the non-key columns are independent of each
other. In other words, the non-key columns are dependent on the primary
key, only on the primary key and nothing else. For example, suppose that we
have a Products table with columns productID (primary
key), name and unitPrice. The column discountRate shall not belong
to Products table if it is also dependent on the unitPrice, which is not part
of the primary key.

At times, you may decide to break some of the normalization rules, for
performance reason (e.g., create a column called totalPrice in
the Orders table which can be derived from the orderDetails records); or
because the end-user requested for it. Make sure that you are fully aware of
it, develop programming logic to handle it, and properly document the
decision.

Integrity Rules
You should also apply the integrity rules to check the integrity of your
design:

Entity Integrity Rule

The primary key cannot contain NULL. Otherwise, it cannot uniquely


identify the row. For composite key made up of several columns, none of the
columns can contain NULL. Most of the RDBMS check and enforce this rule.

Referential Integrity Rule

Each foreign key value must be matched to a primary key value in the table
referenced (or parent table).

You can insert a row with a foreign key in the child table only if the
value exists in the parent table.
If the value of the key changes in the parent table (e.g., the row
updated or deleted), all rows with this foreign key in the child
table(s) must be handled accordingly. You could either (a) disallow
the changes; (b) cascade the change (or delete the records) in the
child tables accordingly; (c) set the key value in the child tables to
NULL.

Most RDBMS can be set up to perform the check and ensure the referential
integrity, in a specified manner.

Business logic Integrity

Besides the above two general integrity rules, there could be integrity
(validation) pertaining to the business logic, e.g., zip code shall be 5-digit
within a certain ranges, delivery date and time shall fall in the business
hours; quantity ordered shall be equal or less than quantity in stock, etc.
These could be carried out in a validation rule (for the specific column) or
programming logic.
Column Indexing

You can create an index on selected column(s) to facilitate data searching


and retrieval. An index is a structured file that speeds up data access
for SELECT, but may slow down INSERT, UPDATE, and DELETE. Without an index
structure, to process a SELECT query with a matching criterion (e.g., SELECT *
FROM Customers WHERE name='Tan Ah Teck'), the database engine needs to
compare every record in the table. A specialized index can reach the record
without comparing every record. However, the index needs to be rebuilt
whenever a record is changed, which results in overhead associated with
using indexes.

An index can be defined on a single column, a set of columns (called


concatenated index), or part of a column (e.g., first 10 characters of
a VARCHAR(100)) (called partial index). You can build more than one index in a
table. For example, if you often search for a customer using
either customerName or phoneNumber, you could speed up the search by
building an index on the column customerName, as well as phoneNumber. Most
RDBMS builds an index on the primary key automatically.

REFERENCES & RESOURCES

"Database design basics (Microsoft Access 2007)", available


at http://office.microsoft.com/en-us/access/HA012242471033.aspx.
Paul Litwin, "Fundamentals of Relational Database Design", available
at http://www.deeptraining.com/litwin/dbdesign/FundamentalsOfRelatio
nalDatabaseDesign.aspx.
Codd E. F., "A Relational Model of Data for Large Shared Data Banks",
Communications of the ACM, vol. 13, issue 6, pp. 377–387, June 1970.
Let's Model a Relational Database
For this exercise, we're going to model a very simple example of the
database needed for a social network.

Step 1: What is the purpose?

The purpose of this database is to store information about users, a user's


posts, a user's images, and a user's friends to be used for a social media
application.

Step 2: Gather data, organize data into tables, and identify primary
keys

I like to start this process by thinking about the primary data elements that
we'll be dealing with. As mentioned above these elements will be:

Users (a single user can have many posts, one to many)


Posts (a single post can have one user/author, one to one)
Images (a single post may or may not have a single image - one to
one)
Friends (all users can have many friends, many to many)

So, let's start building out these tables. Remember, each table should ONLY
contain fields that correspond directly to that table's element.

The Users Table:

UserId
int, primary key, required
First Name
varchar, required
Last Name
varchar, required
Email
varchar, required
DateCreated
varchar, required

The Posts Table:


PostId
int, primary key
UserId
int, foreign key, required
Foreign Key referencing Users.UserId
PostText
blob, required
ImageId
int, foreign key, optional
Foreign Key references Images.ImageId
Date
date, required

The Images Table:

ImageId
int, primary key
ImageURL
varchar, required
Date
date, required

The Users_Friends Table:

Id
int, primary key
UserId_1
int, foreign key
Foreign Key references Users.UserId
Many-to Many
UserId_2
int, foreign key
Foreign Key references Users.UserId
Many to Many
Date
Step 3 - Create Relationships among Tables

Using the great tool found here, I have created a simple Entity Relationship
Diagram (ERD) to visualize the tables and their relationships with each other.
Notice again how each table ONLY contains fields that explicitly correlate to
the table entity. With a simple relational model like this, we only need to
create a user record once, we only need to create a post record once, we
only need to create an image record once, and we only need to create a
"friends" record once. We will never repeat the same information in any
table. We do not have tables that have a never-ending list of columns like a
spreadsheet from hell. It's a very simple diagram that illustrates the data we
need to store, in a nice and tidy fashion and the relationships between the
data.
Here is the code I used while creating diagram above:

Users
---
UserId PK int
FirstName string
LastName string
Email string
DateCreated date

Images
---
ImageId PK int
ImageURL string
Date date
Posts
---
PostId PK int
UserId int FK >- Users.UserId
PostText blob
ImageId int FK >- Images.ImageId
Date date

Users_Friends
---
Id PK int
UserId_1 int FK >- Users.UserId
UserId_2 int FK >- Users.UserId
Date date

In the next section, we'll create the DB Schema and tables. Let's do it!
Creating DB Schema & Tables
Now that we understand the basics of Relational Databases, and how to
model them. Let's go ahead and create one by following the steps below.

1. Make sure that MySQL is installed on your machine


1. You can check this by running mysql --version from the CLI.
2. If it is not installed please refer to this page before proceeding.
2. Make sure MySQL is running on your machine
1. Mac:
1. sudo /usr/local/mysql/support-files/mysql.server start
- or
2. sudo launchctl load -F
/Library/LaunchDaemons/com.oracle.oss.mysql.mysqld.plis
t
2. Linux:
1. /etc/init.d/mysqld start - or
2. service mysqld start - or
3. service mysql start
3. Windows:
1. C:\>"C:\Program Files\MySQL\MySQL Server
8.0\bin\mysqld"
3. Open MySQLWorkbench
4. Open/Connect to "localhost" connection
1. If you have not set up the "localhost" connection please refer here.
5. In the open query tab, run the following SQL command, then execute it
by clicking the lightning bolt.

create schema SocialDB;

6. Refresh the "schemas" tab on the left side of the screen to see the new
schema appear by clicking the refresh icon - the two spinning arrows.
7. Expand the SocialDB Schema by clicking the arrow next to it.

8. Right-click on "Tables" and select "Create Table"

9. Create the Users table to match the image below:


Notice how the UserId has the "AI" checked - this means
"Auto Increment"
Notice how the DateCreated field sets the default TimeStamp
to the "Current_Timestamp"

10. Click "Apply" then "Apply" again to execute the following SQL
statement:

CREATE TABLE `SocialDB`.`Users` (


`UserId` INT NOT NULL AUTO_INCREMENT,
`FirstName` VARCHAR(100) NOT NULL,
`LastName` VARCHAR(100) NOT NULL,
`Email` VARCHAR(100) NOT NULL,
`DateCreated` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TI
PRIMARY KEY (`UserId`));

11. Create the Images tables to match the image below:

12. Click "Apply" and then "Apply" again to execute the following SQL:

CREATE TABLE `Images` (


`ImageId` INT NOT NULL AUTO_INCREMENT,
`ImageURL` VARCHAR(250) NOT NULL,
`Date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAM
PRIMARY KEY (`ImageId`))

13. Create the Posts table to match the image below:

14. Click "Apply" then "Apply" again to execute the following SQL:

CREATE TABLE `SocialDB`.`Posts` (


`PostId` INT NOT NULL AUTO_INCREMENT,
`UserId` INT NOT NULL,
`PostText` VARCHAR(500) NOT NULL,
`ImageId` INT NULL,
`Date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAM
PRIMARY KEY (`PostId`));

15. After the table has been created, let's go create the foreign key
constraint for the UserId field (which will reference the UserId field in
the Users table). First, from the same table editor window, click on the
"Foreign Keys" tab towards the bottom of the window.

16. Create the foreign key to match the image below:

17. Click "Apply" then "Apply" to execute the following SQL:

ALTER TABLE `SocialDB`.`Posts`


ADD CONSTRAINT `UserId`
FOREIGN KEY (`UserId`)
REFERENCES `SocialDB`.`Users` (`UserId`)
ON DELETE CASCADE
ON UPDATE CASCADE;

In the SQL above we have set it so that when a User is deleted or


updated, those changes will CASCADE into the Posts table. Since there
is no reason for us to keep posts for a user who has been deleted, we
can also delete the posts associated with them. This is called a
CASCADE.
18. Create the Users_Friends table to match the image below:
19. Click "Apply" then "Apply" to execute the following SQL:

CREATE TABLE `Users_Friends` (


`Id` INT NOT NULL AUTO_INCREMENT,
`UserId_1` INT NOT NULL,
`UserId_2` INT NOT NULL,
`Date` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
PRIMARY KEY (`Id`));

20. Now let's create the foreign keys required for this table. Start by clicking
on the "foreign keys" tab again.

21. Add the foreign keys to match the image below:

22. Click "Apply" then "Apply" again to execute the following SQL:

ALTER TABLE `SocialDB`.`Users_Friends`


ADD INDEX `UserId_1_idx` (`UserId_1` ASC),
ADD INDEX `UserId_2_idx` (`UserId_2` ASC);
ALTER TABLE `SocialDB`.`Users_Friends`
ADD CONSTRAINT `UserId_1`
FOREIGN KEY (`UserId_1`)
REFERENCES `SocialDB`.`Users` (`UserId`)
ON DELETE CASCADE
ON UPDATE CASCADE,
ADD CONSTRAINT `UserId_2`
FOREIGN KEY (`UserId_2`)
REFERENCES `SocialDB`.`Users` (`UserId`)
ON DELETE CASCADE
ON UPDATE CASCADE;

If you have trouble following the instructions above, you can also run the
following SQL to create all the tables and constraints at once. (Though we
highly recommend manually creating each table as this is something you'll
need to do again and again.)

CREATE DATABASE IF NOT EXISTS `SocialDB` /*!40100 DEFAULT CHARACTER SET latin1 */
USE `SocialDB`;
-- MySQL dump 10.13 Distrib 5.7.17, for macos10.12 (x86_64)
--
-- Host: 127.0.0.1 Database: SocialDB
-- ------------------------------------------------------
-- Server version 5.7.17

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;


/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Table structure for table `Images`
--

DROP TABLE IF EXISTS `Images`;


/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `Images` (
`ImageId` INT NOT NULL AUTO_INCREMENT,
`ImageURL` VARCHAR(250) NOT NULL,
`Date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
PRIMARY KEY (`ImageId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `Images`
--

LOCK TABLES `Images` WRITE;


/*!40000 ALTER TABLE `Images` DISABLE KEYS */;
/*!40000 ALTER TABLE `Images` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `Posts`
--

DROP TABLE IF EXISTS `Posts`;


/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `Posts` (
`PostId` INT NOT NULL AUTO_INCREMENT,
`UserId` INT NOT NULL,
`PostText` blob NOT NULL,
`ImageId` INT DEFAULT NULL,
`Date` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`PostId`),
KEY `UserId_idx` (`UserId`),
CONSTRAINT `UserId` FOREIGN KEY (`UserId`) REFERENCES `Users` (`UserId`) ON
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `Posts`
--

LOCK TABLES `Posts` WRITE;


/*!40000 ALTER TABLE `Posts` DISABLE KEYS */;
/*!40000 ALTER TABLE `Posts` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `Users`
--

DROP TABLE IF EXISTS `Users`;


/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `Users` (
`UserId` INT NOT NULL AUTO_INCREMENT,
`FirstName` VARCHAR(100) NOT NULL,
`LastName` VARCHAR(100) NOT NULL,
`Email` VARCHAR(100) NOT NULL,
`DateCreated` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTA
PRIMARY KEY (`UserId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `Users`
--
LOCK TABLES `Users` WRITE;
/*!40000 ALTER TABLE `Users` DISABLE KEYS */;
/*!40000 ALTER TABLE `Users` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `Users_Friends`
--

DROP TABLE IF EXISTS `Users_Friends`;


/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `Users_Friends` (
`Id` INT NOT NULL AUTO_INCREMENT,
`UserId_1` INT NOT NULL,
`UserId_2` INT NOT NULL,
`Date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
PRIMARY KEY (`Id`),
KEY `UserId_1_idx` (`UserId_1`),
KEY `UserId_2_idx` (`UserId_2`),
CONSTRAINT `UserId_1` FOREIGN KEY (`UserId_1`) REFERENCES `Users` (`UserId`)
CONSTRAINT `UserId_2` FOREIGN KEY (`UserId_2`) REFERENCES `Users` (`UserId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `Users_Friends`
--

LOCK TABLES `Users_Friends` WRITE;


/*!40000 ALTER TABLE `Users_Friends` DISABLE KEYS */;
/*!40000 ALTER TABLE `Users_Friends` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;


/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
Let's Add Some Data!
Using MySQL Workbench (which we'll just call "Workbench" from here out)
we can very easily insert a few rows into each table, much like we would a
spread sheet. Here's how we'll do it:

1. Close all open query tabs in Workbench just so we have a nice clear
slate.
2. In the navigation panel in the left, double click on "SocialDB" so that it is
now highlighted (or bold). This will set SocialDB as the default database
you want to run your queries against. It is possible, and common, to
manage multiple databases from within Workbench.
3. Beside the "Users" table, click on the little icon that looks like a
spreadsheet with a lightning bolt in it.

4. You should see a screen like this:


5. Now simply add some values. We don't need to add values for UserId or
DateCreated as though are generated automatically. UserId is auto
increment, which means it will automatically increment the value from
the last entry. And DateCreated will default to the current date.

6. Add a few more rows and click "Apply" to execute SQL along these
lines:

INSERT INTO `SocialDB`.`Users` (`FirstName`, `LastName`, `Email`) VALUES (


INSERT INTO `SocialDB`.`Users` (`FirstName`, `LastName`, `Email`) VALUES (
INSERT INTO `SocialDB`.`Users` (`FirstName`, `LastName`, `Email`) VALUES (
INSERT INTO `SocialDB`.`Users` (`FirstName`, `LastName`, `Email`) VALUES (

7. Now run

SELECT * FROM SocialDB.Users;

again by clicking the lightning bolt up top. You will see that the records
have been created and the automatic fields have been populated.
8. Let's do the same for our Images table:

9. Click "Apply" to execute code along these lines:

INSERT INTO `SocialDB`.`Images` (`ImageURL`) VALUES ('http://www.maravipost.com/


INSERT INTO `SocialDB`.`Images` (`ImageURL`) VALUES ('https://i.pinimg.com/origi
INSERT INTO `SocialDB`.`Images` (`ImageURL`) VALUES ('https://i.pinimg.com/origi
INSERT INTO `SocialDB`.`Images` (`ImageURL`) VALUES ('https://i.pinimg.com/origi

10. And again with the Posts table:

11. Click "Apply" to run SQL along these lines:

INSERT INTO `SocialDB`.`Posts` (`UserId`, `PostText`, `ImageId`) VALUES (


INSERT INTO `SocialDB`.`Posts` (`UserId`, `PostText`, `ImageId`) VALUES (
INSERT INTO `SocialDB`.`Posts` (`UserId`, `PostText`, `ImageId`) VALUES (
INSERT INTO `SocialDB`.`Posts` (`UserId`, `PostText`, `ImageId`) VALUES (

12. Lastly, let's connect some friends:


13. Click "Apply" to run SQL along these lines:

INSERT INTO `SocialDB`.`Users_Friends` (`UserId_1`, `UserId_2`) VALUES ('1'


INSERT INTO `SocialDB`.`Users_Friends` (`UserId_1`, `UserId_2`) VALUES ('1'
INSERT INTO `SocialDB`.`Users_Friends` (`UserId_1`, `UserId_2`) VALUES ('1'
INSERT INTO `SocialDB`.`Users_Friends` (`UserId_1`, `UserId_2`) VALUES ('2'
INSERT INTO `SocialDB`.`Users_Friends` (`UserId_1`, `UserId_2`) VALUES ('3'

Nice! We've done it! We've created a simple relational database, we've
drawn correlations (using primary and foreign keys) between tables, and
we've add a bit of data.

Below is a little sneak peek at some of the amazing things we can now do
with this relational database. In query below we're joining the Users table,
the Posts table and the Images table to get the user's first name and last
name (from the Users table), the PostText (from the Posts table) and the
image URL (from the images table) all in a single query!

select u.FirstName, u.LastName, p.PostText, i.ImageURL


from Users u
join Posts p
on p.UserId = u.UserId
join Images i
on p.ImageId = i.ImageId
where u.UserId = 1;

And the result looks like this:


Pretty freakin sweet, right?! Also, if you're curious, here's a clickable link to
the funny image in my first social post.

Now, let's take a closer look at all the wonderful queries we can run on this
database (and any other)!
 Dashboard / My courses / SQL & Databases / Sections / 3) Creating Relational Databases
/ Travel/Tour Company Database

Travel/Tour Company Database

Please list out the tables (and their Celds) required to create a relational database used in a travel/tour company. There
are many ways to go about this. There is no single "correct" answer. If you were building an application to manage a
travel/tour company, what would the database behind that application look like? Please note all datatypes, primary keys
and foreign keys.

Example:

Table: Employees
-----------------
employee_id INT auto-increment primary key
first_name VARCHAR NOT NULL
last_name VARCHAR NOT NULL
email VARCHAR NOT NULL
hire_date DATE NOT NULL

...

Submission status

Submission status No attempt

Mentor Review Status Review Pending (1-on-1 mentorship required for assignment review)
          Andrew Francisco

Last modiCed -
Dashboard Course Options Members-Only Forum About
Submission comments
 Comments (0)

Add submission

You have not made a submission yet


◀︎ Video: Creating a Simple Relational Database Working with Primary & Foreign Keys ▶︎

"Success occurs when opportunity meets preparation."

      

You are logged in as Andrew Francisco (Log out)

Copyright © CodingNomads 2022


Working with Primary & Foreign Keys
In the submission box below, or in a file upload please answer the following
questions:

1) What are primary keys?

2) Why do we need/use primary keys?

3) What are foreign keys?

4) Why do we need/use foreign keys?

5) What do the following actions mean?

- ON UPDATE CASCADE

- ON UPDATE NO ACTION

- ON UPDATE RESTRICT

- ON DELETE CASCADE

- ON DELETE NO ACTION

- ON DELETE RESTRICT

6) Please demonstrate a query that will add a foreign key constraint to a


table.

7) Describe the process of adding foreign keys to a table in MySQL


Workbench.

8) What is the most common primary key we use in basically every table we
create?
Importing the Sakila Database
MySQL provides a few very useful demo databases for us to use as we learn
the ropes. You can take a peek at them here under Example Databases. For
the purposes of this tutorial, and learning the basics of SQL, we'll be using
the Sakila Database which you can download here. Under "Example
Databases", save the "sakila database" zip file to your "Downloads" folder.
When the download is complete, unzip the folder. Within the resulting
"unzipped" folder you should see two .sql files - sakila-data.sql and sakila-
schema.sql.

Side note, I know we've just spent some time creating our beautiful custom
database in the previous section, but we'll have to come back to that as the
Sakila DB is just so useful when learning how to use SQL and MySQL.

After downloading the Sakila DB please open MySQL Workbench, open your
connection to "localhost" and navigate to the "Management" tab (for me it's
on the top left).

Once there, click on "Data Import/Restore".


Now, select the radio button for "Import from Self-Contained File" and
navigate to the sakila-schema.sql file (from which to import from) as seen
below.

Click "Start Import" after it completes you will see a screen similar to this:

Great, we've now imported the Sakila Database schema (just the table and
their structure etc). Now, let's import the data by repeating the process of
importing from a self-contained file, but this time we'll choose the sakila-
data.sql file.

To get started, click on "Import from Disk" at the top of the current window:

Select "Import from Self-Contained File" again, and navigate to the sakila-
data.sql file. Then click "Start Import". When that has completed
successfully, go back to the schemas tab:

And refresh all schemas by click the little refresh icon:

At which point you should now see the sakila database.


Now, I'd suggest taking a bit of time to explore this database. Explore each
table by right clicking on the table and running "Select Rows - Limit 1000".
Also, right click on any table and select "Alter Table" to take a look at the
structure of each table.

In addition, run the following queries just to get the lay of the land:

use sakila;

describe actor;

SELECT * FROM actor;

SELECT * FROM sakila.film_actor;


SELECT * FROM sakila.film;

SELECT a.first_name, a.last_name, count(f.title) num_films


from actor a
join film_actor fa
on a.actor_id = fa.actor_id
join film f
on fa.film_id = f.film_id
group by a.first_name, a.last_name
order by num_films desc;
Visualizing the Sakila DB Schema
Here is the ERD (Entity Relationship Diagram) of the Sakila Database. Pretty
neat, eh?
SELECT
SELECT is probably the most common SQL keyword. We use it when we
want to SELECT data from the database. Please note that while we often
capitalize the keywords in SQL, it is not required. It's just a formatting
convention. Also, please note that all SQL commands, when executed within
MySQLWorkbench or the MySQL Shell (CLI) must end with a semicolon.

Note: As MySQL (and MySQL Workbench) are capable of managing many


databases at once. The first query we'll run any time we're working with a
database is:

use <DATABASE_NAME>;

For instance:

use sakila;

This will tell MySQL that the queries we're executing should be executed
against the sakila database. Then we can query directly to the tables. For
instance:

select * from actor;

If you do not run the "use" query you can still execute queries, but you must
indicate the database name in all queries. For instance:

SELECT * FROM sakila.actor;


Example 1)

Let's SELECT all rows and columns from the actor table: (In SQL, "*" means
"ALL")

SELECT * FROM actor;

Output:

Example 2)

Now, let's just SELECT two distinct columns from the actor table, but all
rows.

SELECT first_name, last_name FROM actor;

Output:
Example 3)

Now, let's just SELECT one distinct column from the actor table, but again,
all rows.

SELECT actor_id FROM actor;

Output:
As you can see, the SELECT query is quite simple and intuitive. We can use it
to SELECT data out of the one (or more) tables. (To SELECT data out of more
than one table we use JOIN, which we'll cover shortly).
SELECT DISTINCT
It is often the case where we have multiple records that have similar traits.
For instance, in the query below we have selected all the actors from the
actor table, and we have sorted the actors by first_name. (We sorted them
by first_name by simply clicking on "first_name" in the Result Grid in MySQL
Workbench.) See how we have multiple actors named "ADAM", "ALBERT",
"AUDREY", "BEN" and so on?

But let's say, for some reason, we just want to know the number of distinct
unique names in the actor table. We can do that by using the keyword
"DISTINCT". For example:

SELECT DISTINCT first_name from actor;

Which will give us the following result:


We use the DISTINCT keyword when we want to retrieve only distinct (aka
different) results.

Here's another example, let's say that you're in HR at a big company with
500 employees and you need to figure out how many days of the year it is
someone's, anyone's birthday so that you can bring in some treats. You
don't need to know who's birthday it is, or how many people have birthday's
on that day. You just need to know what dates you need to bring in treats. In
this case you might run a query that looks like:

SELECT DISTINCT birth_day, birth_month FROM employees;

The resulting dataset would then give you a list of distinct dates on which
you need to bring in treats :)
LIMIT
The LIMIT keyword is just a nice little utility helper that will help us LIMIT the
number of results we get back. For instance, let's just select 10 customers:

SELECT * FROM customer


LIMIT 10;

Or, let's take the query we ran in the previous GROUP BY example where we
got the total payments for all customers. But this time, let's limit it to 5
results to just get our 5 best customers so we can send them a thank you
gift over the holidays :)

SELECT c.first_name, c.last_name, SUM(p.amount) as total_payments


FROM customer c
JOIN payment p
ON c.customer_id = p.customer_id
GROUP BY c.customer_id
ORDER BY total_payments DESC
LIMIT 5;
NOTE: The LIMIT clause must always be the last and final clause in the
query. For instance, this will NOT work:

SELECT c.first_name, c.last_name, SUM(p.amount) as total_payments


FROM customer c
JOIN payment p
ON c.customer_id = p.customer_id
GROUP BY c.customer_id
LIMIT 5
ORDER BY total_payments DESC;

The query above will fail because the LIMIT clause must be the last
element/clause in the query.
INSERT
When we need to add data into the database, we use INSERT statements.
With an insert statement we specify the table we want to insert data into, the
columns we want to insert data into, and the values we actually want to be
inserted. For instance:

INSERT INTO sakila.actor


(first_name, last_name) # column names to insert into
VALUES
("Ryan", "Desmond"); # values to insert into those columns (in the same order)

# in SQL, the hashtag or pound sign is the comment symbol, just FYI

Result: (showing one row was affected - which means "success")

In the query above you can see that we are INSERT(ing) INTO the
sakila.actor table. The columns we're inserting into are "first_name" and
"last_name". The values we want inserted into those fields are "Ryan" and
"Desmond".

Note: auto-generated fields such as, in this case "actor_id" and


"last_update" are auto generated by MySQL. So we do not need to manually
insert them. MySQL will auto-generate them. We can verify this by looking at
the table structure:
See how the "actor_id" field has the "AI" box ticked? That "AI" means auto-
increment. This means it will automatically increment the actor_id (based of
the last record) and insert it into all new records. Also note how the
"last_update" field has a "Default / Expression" assigned to
"CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP". This means
that all new records will have the current timestamp automatically inserted
upon insert, as well as ON UPDATE (when the record is updated at any time
it will also update this timestamp).

Here's another INSERT statement, this time for the categories table. In this
case, the categories table only has 3 fields. Two of which are autogenerated.
So all we have to do is INSERT the one non-auto-generated field.

INSERT INTO sakila.category


(name) #column name to insert into
VALUES
("Cartoon"); #value to insert into it

And if we run:

select * from category where name = "Cartoon";

We can see that the record was indeed inserted.


CREATE TABLE SELECT
This is a fun and often handy little query that allows us to create a new table
based on the results of a SELECT query. Here's the syntax:

CREATE TABLE <new_table_name> SELECT * FROM <some_other_table>;

Here's a working example. In this case we're making a full backup of the
actor table.

CREATE TABLE actor_backup SELECT * FROM actor;

And now after we refresh the schema navigator on the left, (by clicking the
little refresh, spinning arrows icon) we can see that we do indeed have a new
table named "actor_backup", which we can select all rows from.
We do not need to select * either. We can just select the rows we want. For
instance, take a look at this query:

CREATE TABLE kids_movies


SELECT title, length, rating
FROM film
WHERE rating = "G"
AND length < 60

With the resulting table as seen below:


This functionality is very handy for creating quick lookup tables (even more
handy with JOIN statements) as well as for creating temporary backups of
tables when you're doing something potentially risky and you want a nice
quick full backup of a table.

I'm going to DROP both of those new tables I created to keep the DB nice
and tidy.

DROP TABLE sakila.kids_movies;

and

DROP TABLE sakila.actor_backup;


UPDATE
Need to update an existing value in the database? This keyword is for you!

When we have an existing record in the DB, and we need to change/update


the value of one or more fields we use the following syntax: (the previous
record I inserted into the actor table in the INSERT section was "Ryan"
"Desmond" and it generated the actor_id of 201 for me. Now I'm going to
update that record.)

UPDATE sakila.actor # table to update


SET first_name = "Bryan", last_name = "Besmond" # fields to be added/updated
WHERE actor_id = 201; # boolean condition

Now, if I run:

SELECT * FROM sakila.actor where actor_id = 201;

I can see that the record was indeed updated.

We can update whatever fields we want, using whatever boolean condition


that works. For instance, I could update every movie in the "film" table with
the rating of "PG" to have a rating of "G" with the following query.

UPDATE `sakila`.`film`
SET rating = "G"
WHERE rating = "PG";

(I'm not actually going to run that query as I don't actually want to make that
update.)
DELETE
When it is time for us to DELETE a record from the one of our
tables, we use the following syntax:

DELETE FROM sakila.actor


WHERE <{where_expression}>;

For instance, let's delete that Bryan Besmond record with


the actor_id of 201:

DELETE FROM sakila.actor


WHERE actor_id = 201;

In the image below we can tell this query was successful by


the number of rows affected that it prints out under
"Response".

Caution!!

If you do not indicate a WHERE clause, you will delete


ALL RECORDS from the table. For instance, the following
query will delete EVERY actor from the actor table:

delete from actor;

It looks harmless enough, but that's a powerful query that


will wipe out all the data in the table. So be careful!
INNER JOIN
Joins are one of the most powerful tools we have in relational databases.
Joins allow us to "join" one or more tables together. For instance, let's take a
look at the following tables:

In the table on the left, the "actors" table, we have information solely about
actors. It doesn't contain any information about any of the films they're in.

In the table in the center, the "film_actor" table, we have a simple lookup
table that contains the fields "actor_id" and "film_id". This is because actors
and films have a many-to-many relationship. So we create lookup tables like
this to associate films with their many actors and actors with their many
films. This allows both the "actor" table and the "film" table to stay nice and
pure and clean.

Then, in the table on the right, the "films" table, we have information solely
about films. It doesn't contain any information about any of the actors in
those films. (This is great relational DB design.)

So how do we write a query that will tell us all the films that a specific actor is
in? Or, how do we write a query that will tell us all the actors in a given film?
We use JOIN queries!

There are several types of JOIN queries. The most prominent are the INNER
JOIN (this is the default join when you just use the "JOIN" keyword), the
LEFT/RIGHT JOIN, FULL JOIN (or UNION) and the OUTER JOIN. In the image
below, it is the YELLOW area that will be returned from JOIN queries.
Let's take a look at the INNER JOIN first.

The INNER JOIN selects all records that have matching values in both
tables.

The way this works is we use columns to join on. To join tables there must be
corresponding columns that have corresponding values. For instance, we
can join the actor table to the film_actor table because they both contain the
field "actor_id". Then, we can join the "film_actor" table with the film table
because they both contain the field "film_id". Let's take a look. Let's select
all the films that the actor "PENELOPE GUINESS" is in.

SELECT actor.first_name, actor.last_name, film.title, film.release_year # fields to


FROM actor #first table to select from
INNER JOIN film_actor # first table to join
ON actor.actor_id = film_actor.actor_id # the field on which to join the two t
INNER JOIN film # second table to join
ON film_actor.film_id = film.film_id # the field on which to join the two table
WHERE actor.first_name = "PENELOPE" AND actor.last_name = "GUINESS"; # boolean cond

Here it is in MySQL Workbench:

There's a lot going on here, let's see if we can unpack it. (The upcoming
video should also help clear it up.)

So, we want to select the first name and last name from the "actor" table,
and the film name and release year from the "film" table. The only way to do
this is to join through the "film_actor" table. This is because the "actor" table
has no data about films whatsoever, and the "film" table has no data about
actors whatsoever. Fortunately, we have this handy "film_actor" table which
links actor_id's with film_id's.
Using this "lookup table" we can now associate the actor with actor_id = 1 to
the film with film_id = 1. As well as the actor with actor_id = 1 to the film with
film_id = 23, and so on. Using this lookup table we can now link the "actor"
table with the "film" table by linking the actor_id from the "actor" table to the
actor_id in the "film_actor" table, and then we link the film_id from the
"film_actor" table to the film_id in the "film" table.

Let's take a look at that query again.


Making a bit more sense now? Maybe? Hopefully? :)

Two notes, since INNER JOIN is the default join we actually don't need to
write the word "INNER". So this query can be re-written as follows:

Additionally, we can further shorten the query by not typing the table names
over and over and over. Instead, we can create aliases (or nicknames) for
each table and then refer to the tables by those aliases. See below:

And here it is again without all the cluttery comments:


Makes perfect sense, right?! Don't worry, if this is a bit confusing at the
moment that is totally normal. It will make sense soon enough! Just keep on
practicing and pushing yourself!
LEFT/RIGHT JOIN
Inner joins return all results where there is a matching record in each table.
But sometimes, we need all the records from one table whether or not there
is a matching record in the join table. In this circumstance, we use the LEFT
and/or RIGHT joins.

A LEFT JOIN will return all rows from the left table (the first one mentioned
in the join clause), even if there's no matching record in the right table.

A RIGHT JOIN will return all rows from the right table (the second one
mentioned in the join clause), even if there's no matching record in the left
table.

An INNER JOIN will only return rows where there's a matching record
in both tables.

By "LEFT" and "RIGHT" it really just means which one you read first or
second. If you want all the records from the table you read first in the query
(whether or not there's a match in the other table), it's a LEFT join. If you
want all the records from the table you read second in the query (whether or
not there are matches in the other table) it's a RIGHT join.

So, let's say we want to get a list of all customers from the customer table,
and we also want to return a list of actors from actor table that share the
same first or last name as the customer. That said, we need the entire list of
customers, whether or not there is an actor with the same first or last name.
In this case, we can use a LEFT JOIN to get all records from the customer
table, as well as any matching records from the actor table. (When there is
no match in the actor table the result will just show NULL for those fields.)

LEFT JOIN
SELECT
c.first_name,
c.last_name,
a.first_name,
a.last_name
FROM customer c
LEFT JOIN actor a
ON c.last_name = a.last_name
ORDER BY c.last_name;

Notice how we read the "customer" table before we read the "actor" table?
Because we're using a LEFT join that means it will select ALL records from
the "customer" table as well as any matching records from the "actor" table.
If there's no match in the actor table it will just show NULL.
RIGHT JOIN

Now, let's take a look at a RIGHT JOIN. To do this, let's simply switch the
word "LEFT" in the query to "RIGHT". The RIGHT JOIN will return all actors
no matter what, as well as any matching records in the customers table.

SELECT
c.first_name,
c.last_name,
a.first_name,
a.last_name
FROM customer c
RIGHT JOIN actor a
ON c.last_name = a.last_name

Notice how we read the "customer" table before we read the "actor" table?
Because we're using a RIGHT join that means it will select ALL records from
the "actor" table as well as any matching records from the "customer" table.
If there's no match in the customer table it will just show NULL.

INNER JOIN (for comparison)

Now, let's say we ONLY want records from the actor table and customer
table where this is a match. We don't care about records from either table
where there is not a match. In this case, we'd use the default INNER join.
Remember here that we don't actually have to type the word "INNER" as the
INNER JOIN is the default join MySQL uses when you use the keyword
"JOIN" all by itself.

SELECT
c.first_name,
c.last_name,
a.first_name,
a.last_name
FROM customer c
INNER JOIN actor a
ON c.last_name = a.last_name
Quick note, MySQL does not support the FULL OUTER JOIN you see in this
table.

Shout out
to https://www.quackit.com/mysql/examples/mysql_left_join.cfm for helping
me come up with some good LEFT and RIGHT join examples for this page.
UNION
UNION vs. JOIN

A JOIN combines result sets horizontally, a UNION appends result set


vertically. The following picture illustrates the difference between UNION and
JOIN: (source)

So, let's say for some reason we want to know all the names of all customers
and all actors in a single result set. In this case we could run the following
query:

select first_name, last_name


from actor
UNION
select first_name, last_name
from customer

And the result set we get back will be a list of all actors and customers,
without any duplicates.
One add-on to the UNION keyword is "UNION ALL". If you modify the query
to say UNION ALL you will indeed get duplicates in the result set should they
exist.

select first_name, last_name


from actor
UNION ALL
select first_name, last_name
from customer;

Notice how there are two additional records returned from this query (799
vs. 797).
SUM / AVG / COUNT
In MySQL, and all other common databases there are a number of helper
functions such as SUM(), COUNT(), AVG().

These functions do exactly as they say. They find the SUM of a given
column, or the COUNT of a number fo records, or the AVERAGE (AVG) of a
given column. So let's take a look.

SUM()

Let's find the sum of all payments in the payments table.

SELECT SUM(amount) FROM payment;

Notice here that the name of the column in the result set is "SUM(amount)".
That's not a great column name. Fortunately, we can rename it very easily
using the "AS" keyword. The "AS" keyword simply allows us to rename the
column in the result set.
Let's run another query just to check the total revenue in the year 2005:

SELECT SUM(amount) AS total_revenue_2005


FROM payment
WHERE payment_date > "2005-01-01"
AND payment_date < "2006-01-01"

COUNT()

Count allows us to count the number of records in a given query. For


example, let's check how many payments we received in 2005:

SELECT COUNT(amount) AS num_payment_2005


FROM payment
WHERE payment_date > "2005-01-01"
AND payment_date < "2006-01-01"
How many actors do we have in the actor table? Let's see!

SELECT COUNT(customer_id) AS customers


FROM customer;

AVG()

The AVG() function (meaning "average") allows us to find the average of a


given field in the result set. For instance, let's figure out what our average
payment amount is.

SELECT AVG(amount) AS avg_payment


FROM payment;
MIN / MAX
Another couple of useful and simple functions in MySQL are the MIN() and
MAX() functions. These functions act exactly as they appear. For instance,
let's query for the largest payment we've received:

SELECT MAX(amount) AS largest_payment


FROM payment;

Inversely, we can also select the lowest payment we've received:

SELECT MIN(amount) AS smallest_payment


FROM payment;
GROUP BY
The GROUP BY statement is used with aggregate functions such as
COUNT(), SUM(), AVG() to group the result-set by one or more columns.

So, suppose we want to know the total number of films each actor has been
in. In order to do this, we need to GROUP BY a field such as actor_id. For
instance:

SELECT a.first_name, a.last_name, COUNT(a.actor_id) as num_films


FROM actor a
JOIN film_actor fa
ON a.actor_id = fa.actor_id
JOIN film f
ON fa.film_id = f.film_id
GROUP BY a.actor_id
ORDER BY num_films DESC;
Or, let's say we want to figure out who our best customer is:

SELECT c.first_name, c.last_name, SUM(p.amount) as total_payments


FROM customer c
JOIN payment p
ON c.customer_id = p.customer_id
GROUP BY c.customer_id
ORDER BY total_payments DESC;
LIKE & Wildcards
Let's say that we want to query all films that start with the letter "P". To do
this we can use the LIKE keyword with the help of the wildcard character
"%". For instance:

SELECT title
FROM film
WHERE title LIKE "P%"

This query will return the titles of all films that start with "P" and are followed
by any other letter.

Let's take another look at the LIKE keyword with the wildcard "%". In this
example, let's find all film titles that contain the letters "cit" anywhere in the
title.

SELECT title
FROM film
WHERE title LIKE "%cit%"

In this query all films that have titles that have any combination of letters
before "cit" and any combination of letters following "cit" will be returned.

Or, how about this query which returns all titles where the letter "e" appears
at least three times. The title must start with "e" and all following "e's" can
be preceded and followed by any other combination of other letters.

SELECT title
FROM film
WHERE title LIKE "e%e%e";
IN
The IN keyword allows you to specify multiple values in the WHERE clause.
The IN keyword is functionally equivalent to having multiple OR boolean
conditions. In the following query, we're selecting all films that were released
in 2004, 2005, or 2006.

select * from film


where release_year IN (2004, 2005, 2006);

The query above is functionally equivalent to the query below:

select * from film


where release_year = 2004
or release_year = 2005
or release_year = 2006;
BETWEEN
The BETWEEN keyword allows us to select all records in between two
values. For instance, let's find out how many payments we've received that
are BETWEEN $3 and $5:

select count(payment_id) as num_payments


from payment
where amount between 3 and 5;

This query above is functionally equivalent to query below:

select count(payment_id) as num_payments


from payment
where amount >= 3 and amount <= 5;
ANY / ALL
The ANY and ALL keywords allow us to use subqueries within our WHERE
clause. For instance, let's say we want to query the first and last names of
every customer who made a rental between 2005-05-25 and 2005-05-30.
To do this we could use the following ANY query:

ANY

SELECT first_name, last_name


from customer c
where customer_id =
ANY (select customer_id
from rental
where rental_date
between "2005-05-25" and "2005-05-30");

ALL
The ALL operator returns TRUE if all of the subquery values meet the
condition.

SELECT first_name, last_name


from customer c
where customer_id =
ALL (select customer_id
from rental
where rental_date = "2005-05-25");
Working with Stored Procedures
A Stored Procedure is simply a SQL query that you save inside the actual
database engine (ie, MySQL). It's one of those queries that you just don't
want to have to write over and over. You just want to save it in one spot and
then anyone with access to that database can then invoke that procedure
any time they want.

For instance, let's say that we want all of our employees to be able to quickly
pull up the top 10 customers, because all top 10 customers get 10% off all
their rentals. But not all of our employees are so great at joins and aggregate
functions and so forth. In this case, the handy SQL wizard can simply store
the query as a stored procedure in the database, and then all of the
employees can just call that procedure to get the top 10 employees and time
they want without really having to write any SQL. Pretty cool, eh? Totally!

So let's do it! Let's use MySQL Workbench and type in the following SQL:

DELIMITER //
CREATE PROCEDURE GetTop10Customers()
BEGIN
SELECT c.first_name, c.last_name, SUM(p.amount) as total_payments
FROM customer c
JOIN payment p
ON c.customer_id = p.customer_id
GROUP BY c.customer_id
ORDER BY total_payments DESC
limit 10;
END //
DELIMITER ;

Then, refresh the schema with the little refresh icon (the circular spinning
arrows) and expand the Stored Procedures section of the schema.
Then, to invoke the stored procedure you use the following SQL:

CALL `sakila`.`GetTop10Customers`();

Breaking down the SQL syntax to create the Stored Procedure

# DELIMTER is used to tell mysql that the semi-colon is no longer used to end the q
# this is because the SQL we're executing to create the procedure contains a SQL quer
# a semi-colon - so we need to tell MySQL that, for the moment, the "//" is what will
DELIMITER //

# SQL syntax to create a stored procedure with the name "GetTop10Customers"


CREATE PROCEDURE GetTop10Customers()
BEGIN

# This is the actual query that we want to store as the procedure itself
# -------------------------------------------------------------------------------
SELECT c.first_name, c.last_name, SUM(p.amount) as total_payments
FROM customer c
JOIN payment p
ON c.customer_id = p.customer_id
GROUP BY c.customer_id
ORDER BY total_payments DESC
limit 10;
# Here is where the actual query that we want to store as the procedure itself en
# -------------------------------------------------------------------------------

# END // is used to indicate that "//" is no longer the active delimiter


END //

# set the delimiter to the semi-colon again (aka what marks the end of the SQL statem

DELIMITER ;
Using MySQL from the CLI
While using MySQL Workbench is definitely a nicer user interface for
interacting with MySQL databases, it is often useful and/or expedient to
connect to MySQL from the CLI. Fortunately, this is simple enough.

Before running the commands below, please ensure that you have started
MySQL.

To connect to MySQL using the "root" user:

mysql -u root -p

After entering the (strong) password you created and saved during the
installing you should see an image the resembles the following:

This means you have successfully connected to MySQL and are now with
the "MySQL Shell" - which is basically a unique and specific CLI environment
just for managing your MySQL databases.

Useful MySQL Shell Commands (source):


Create a database.

mysql> create database [databasename];

List all databases on the server.

mysql> show databases;

Switch to a database.

mysql> use [db name];

To see all the tables in the db.

mysql> show tables;

To see table's field formats.

mysql> describe [table name];

To delete a db.

mysql> drop database [database name];

To delete a table.

mysql> drop table [table name];

Show all data from a table.

mysql> SELECT * FROM [table name];

To return columns and column information.

mysql> show columns from [table name];

Show particular rows with the given value.


mysql> SELECT * FROM [table name] WHERE [field name] = "value";

Creating a new user. Login as root. Switch to the MySQL db. Make
the user. Update privs.

# mysql -u root -p
mysql> use mysql;
mysql> INSERT INTO user (Host,User,Password)
VALUES('%','username',PASSWORD('password'));
mysql> flush privileges;

Change a users password from unix shell.

# [mysql dir]/bin/mysqladmin -u username -h hostname -ppassword 'new-


password'

Change a users password from MySQL prompt. Login as root. Set


the password. Update privileges.

# mysql -u root -p
mysql> SET PASSWORD FOR 'user'@'hostname' = PASSWORD('password');
mysql> flush privileges;

Recover a MySQL root password. Stop the MySQL server process.


Start again with no grant tables. Login to MySQL as root. Set new
password. Exit MySQL and restart MySQL server.

# /etc/init.d/mysql stop
# mysqld_safe --skip-grant-tables
# mysql -u root
mysql> use mysql;
mysql> update user set password=PASSWORD("newpassword") where
User='root';
mysql> flush privileges;
mysql> quit
# /etc/init.d/mysql stop
# /etc/init.d/mysql start

Set a root password if there is no root password.

# mysqladmin -u root password newpassword

Update a root password.

# mysqladmin -u root -p oldpassword newpassword

Allow the user "Someone" to connect to the server from localhost


using the password "passwd". Login as root. Switch to the MySQL
db. Give privs. Update privs.

# mysql -u root -p
mysql> use mysql;
mysql> grant usage on *.* to Someone@localhost identified by 'passwd';
mysql> flush privileges;

Load a CSV file into a table.

mysql> LOAD DATA INFILE '/tmp/filename.csv' replace INTO TABLE [table


name] FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n'
(field1,field2,field3);

Dump all databases for backup. Backup file is sql commands to


recreate all db's.

# mysqldump -u username -ppassword --opt > /tmp/alldatabases.sql

Dump one database for backup.

# mysqldump -u username -ppassword --databases databasename >


/tmp/databasename.sql
Dump a table from a database.

# mysqldump -u username -ppassword databasename tablename >


/tmp/databasename.tablename.sql

Restore database (or database table) from backup.

# mysql -u username -ppassword databasename < /tmp/databasename.sql

Create Table Example 1.

mysql> CREATE TABLE [table name] (name VARCHAR(20));

Create Table Example 2.

mysql> create table [table name] (personid int(50) not null auto_increment
primary key,firstname varchar(35),middlename
varchar(50),lastnamevarchar(50) default 'somethiing');
Importing & Exporting Schemas and
Data from CLI
MySQL has made it wonderfully easy for us to create backups of our
databases (exporting schemas and data) as well as to restoring databases
from backups (importing schemas and data).

We can do this either from the CLI or from MySQL Workbench. In this
section, we'll cover how to go about it from the CLI.

In the steps below we'll create a backup of the Sakila DB and we'll save it to
our Desktop, then we'll drop (delete) the Sakila DB and verify that it has
indeed been deleted, then we'll restore the Sakila DB from our backup.

Step 1) Create the backup

1. Open the CLI


2. type mysql -u root -p and hit ENTER
3. enter your root password to login into the MySQL Shell
4. type the MySQL command show databases; and hit ENTER
5. verify that the Sakila DB is indeed present
+--------------------------+
| Database |
+--------------------------+
| information_schema |
| sakila |
+--------------------------+
6. type the MySQL command exit; and hit ENTER
7. now, outside the mysql shell type the command mysqldump -u root -p
sakila > ~/Desktop/sakila_backup.sql and hit ENTER
8. enter your MySQL password once again and hit ENTER
9. type the command ls -al ~/Desktop and hit ENTER
10. verify that the file "sakila_backup.sql" exists on your desktop
11. type the command cat ~/Desktop/sakila_backup.sql and hit ENTER
and watch all the data fly by
12. SUCCESS! We've created the backup. That sakila_backup.sql file
contains all the schema information and all the data contained in the
Sakila DB.

Step 2) Deleting the Sakila DB from MySQL

1. Let's log in to the mysql shell again - type mysql -u root -p and hit
ENTER
2. enter your root password to login into the MySQL Shell
3. type the MySQL command drop schema sakila; and hit ENTER
4. type the MySQL command show databases; and hit ENTER
5. Verify that the sakila db is NOT present
6. Oh no! What have we done! We deleted the whole database!!! :) (Not to
worry! We made a backup just a second ago!)

Step 3) Restoring the Sakila DB from the backup file

1. From within the MySQL shell, let's create an empty schema by typing
the MySQL command create schema sakila; and hit ENTER
2. type the MySQL command exit; and hit ENTER
3. type the command mysql -u root -p sakila <
~/Desktop/sakila_backup.sql and hit ENTER
4. enter your password - wait for the process to complete

Step 4) Verify that the Sakila DB was restored

1. Let's log in to the mysql shell again - type mysql -u root -p and hit
ENTER
2. Enter your root password to login into the MySQL Shell
3. Type the MySQL command show databases; and hit ENTER
4. Verify that the sakila DB is now present again
5. Type the MySQL command use sakila; and hit ENTER
6. Type the MySQL command select * from actor limit 10; and hit
ENTER
7. TADA!!! WE DID IT!
Importing & Exporting Schemas and
Data from MySQL Workbench
We can also very easily import and export data using MySQL Workbench.
We've actually already done the import when we initially imported the Sakila
DB back in the beginning of this module. That said, let's do the whole
process from scratch.

In the steps below we will:

1. Create a backup of the sakila DB


2. Drop the sakila DB
3. Restore the sakila DB
4. Verify that the sakila DB is back in action

Step 1) Creating the backup of the Sakila DB

1. Open MySQL Workbench


2. Connect to your "localhost" connection
3. Once connected, click on the "Management" tab

4. Now click on "Data Export"


5. Now check the box next to the "sakila" database
6. Ensure that all the boxes are checked in the "Schema Objects" window
7. Down below, check the radio button for "Export to a Self-Contained
File"
8. Choose a location to save the file to
9. Check the boxes next to "Create Dump in a Single Transaction" as well
as "Include Create Schema"

10. Click "Start Export"


11. Wait for it to finish

Step 2) Dropping the Sakila DB

1. Head back over to the Schemas tab (just beside the "Management"
tab)
2. Right click on the sakila schema and select "Drop Schema"
3. Click "Drop Now"
4. Verify that the sakila DB is gone
5. Oh NO!!! What have we done?!?! :) jk - we're all good!

Step 3) Restoring the Sakila DB from the backup file

1. Go back over to the "Management" tab


2. Select "Data Import / Restore"
3. Select "Import from a Self-Contained File" and navigate to the dump file
we just created
4. Under "Default Schema to be Imported to", click "New" and type
"sakila" in the input area - hit ENTER

5. Click "Start Import"


6. Wait for it to finish

Step 4) Verify that we have indeed restored the Sakila DB

1. Head back over to the "Schemas" tab


2. Click the little refresh icon - the spinning arrows
3. Verify that you can see the sakila schema
4. Expand the sakila schema
5. Expand the tables
6. Right click on actor
7. Select "Select Rows - Limit 1000"
8. TADA!!! :)
ORDER BY
ORDER BY is a very nice little utility keyword that allows us to order our
results. For instance, let's say we want to select all actors and order them by
their first names in descending fashion (from A to Z). To do this we could run
this query:

SELECT * from actor


ORDER BY first_name ASC;

Notice that we use the letters "asc" for "ascending". Inversely, we use the
letters "desc" for "descending". It's all about keeping the queries as neat
and tidy as possible!

Let's run that same query but ORDER BY the last names in a DESC fashion:
SELECT * from actor
ORDER BY last_name DESC;

Lastly, let's just order the actors by their actor_id's. (It will order by "ASC" by
default.)

SELECT * from actor


ORDER BY actor_id;
AND / OR / NOT
In SQL we have the same logical operator AND, OR and NOT as we have in
programming. For instance, let's say it's almost bedtime for the kiddos and
we're looking for a short movie that is child-friendly (with a rating of "G").
We could run the following query to filter on both of those conditions:

AND

SELECT * FROM film WHERE length < 50 AND rating = "G";

This query will only return results from the film table WHERE the length of
the film is less than 50 AND the rating of the film is "G".

OR

Let's say that our kids are a bit old and they can watch both "G" movies as
well as "PG" movies. In this case we can select all films from the film table
that have a rating of "G" OR "PG".

SELECT * FROM sakila.film where rating = "G" OR rating = "PG";


We can continue to tack on additional OR clauses (as well as AND and NOT)
clauses as well. For instance:

SELECT * FROM sakila.film where rating = "G" OR rating = "PG" OR rating = "PG-13"

NOT

Ok, so let's say our kids are even a bit older now and they can watch just
about any movie so long as it does NOT have the rating of "NC-17". As these
movies are only for the adults. In this case, we can run a query like this:

SELECT * FROM sakila.film where NOT rating = "NC-17";

In this case, we're saying return all rows where the rating is NOT "NC-17".
The use of AND, OR and NOT is very common in day-to-day queries to help
us filter our queries on multiple boolean conditions.
SELECT - WHERE
Now that we understand how to SELECT all data from a given table, it's time
to understand how to filter that data. For instance, let's say that we want to
select all actors from the actors table with the first name "Julia". But, we
ONLY want to select actors with the first name "Julia". In this case, and in so
many others we use the "WHERE" clause. The WHERE keyword is used to
filter results to those who pass a certain boolean condition. For instance:

SELECT * FROM sakila.actor WHERE first_name = "JULIA";

With the result:

Or, let's say we only want to retrieve the actor who has the actor_id of 123.

SELECT * FROM sakila.actor WHERE actor_id = 123;

With the result:


And we can go on and on like this only selecting records WHERE a certain
condition is true. For instance:

SELECT * FROM sakila.film WHERE length > 184;


Managing Databases
In the submission box below, or in a file upload:

1) Please list out the exact steps to export a database from MySQL using the
CLI.

2) Please list out the exact steps to import a database from MySQL using the
CLI.

3) Please list out the exact steps to export a database from MySQL using
MySQL Workbench.

4) Please list out the exact steps to import a database from MySQL using
MySQL Workbench.

Submission status

Submission status No attempt


Mentor Review Review Pending (1-on-1 mentorship required for
Status assignment review)
Last modified -
Submission
comments

You have not made a submission yet


 Dashboard / My courses / SQL & Databases / Sections / 7) Extended MySQL Functions Reference
/ Function and Operator Reference

Function and Operator Reference

Sourced from MySQL Docs here: https://dev.mysql.com/doc/refman/8.0/en/built-in-function-reference.html

Name Description
ABS() Return the absolute value
ACOS() Return the arc cosine
ADDDATE() Add time values (intervals) to a date value
ADDTIME() Add time
AES_DECRYPT() Decrypt using AES
AES_ENCRYPT() Encrypt using AES
AND, && Logical AND
ANY_VALUE() Suppress ONLY_FULL_GROUP_BY value rejection
ASCII() Return numeric value of left-most character
ASIN() Return the arc sine
Assign a value (as part of a SET statement, or as part of the SET clause
=
in an UPDATEstatement)
:= Assign a value
ASYMMETRIC_DECRYPT() Decrypt ciphertext using private or public key
ASYMMETRIC_DERIVE() Derive symmetric key from asymmetric keys
ASYMMETRIC_ENCRYPT() Encrypt cleartext using private or public key
ASYMMETRIC_SIGN() Generate signature from digest
ASYMMETRIC_VERIFY() Verify that signature matches digest
ATAN() Return the arc tangent
ATAN2(), ATAN() Return the arc tangent of the two arguments
AVG() Return the average value of the argument
BENCHMARK() Repeatedly execute an expression
BETWEEN ... AND ... Check whether a value is within a range of values
BIN() Return a string containing binary representation of a number
BIN_TO_UUID() Convert binary UUID to string
BINARY Cast a string to a binary string
BIT_AND() Return bitwise AND
BIT_COUNT() Return the number of bits that are set
BIT_LENGTH() Return length of argument in bits
BIT_OR() Return bitwise OR
BIT_XOR() Return bitwise XOR
& Bitwise AND
~ Bitwise inversion
| Bitwise OR
^ Bitwise XOR
CAN_ACCESS_COLUMN() Internal use only
CAN_ACCESS_DATABASE() Internal use only
CAN_ACCESS_TABLE() Internal use only
CAN_ACCESS_VIEW() Internal use only
CASE Case operator
CAST() Cast a value as a certain type
CEIL() Return the smallest integer value not less than the argument
CEILING() Return the smallest integer value not less than the argument
CHAR() Return the character for each integer passed
CHAR_LENGTH() Return number of characters in argument
CHARACTER_LENGTH() Synonym for CHAR_LENGTH()
CHARSET() Return the character set of the argument
COALESCE() Return the ^rst non-NULL argument
COERCIBILITY() Return the collation coercibility value of the string argument
COLLATION() Return the collation of the string argument
COMPRESS() Return result as a binary string
CONCAT() Return concatenated string
CONCAT_WS() Return concatenate with separator
CONNECTION_ID() Return the connection ID (thread ID) for the connection
CONV() Convert numbers between different number bases
CONVERT() Cast a value as a certain type
CONVERT_TZ() Convert from one time zone to another
COS() Return the cosine
COT() Return the cotangent
COUNT() Return a count of the number of rows returned
COUNT(DISTINCT) Return the count of a number of different values
CRC32() Compute a cyclic redundancy check value
CREATE_ASYMMETRIC_PRIV_KEY() Create private key
CREATE_ASYMMETRIC_PUB_KEY() Create public key
CREATE_DH_PARAMETERS() Generate shared DH secret
CREATE_DIGEST() Generate digest from string
CUME_DIST() Cumulative distribution value
CURDATE() Return the current date
CURRENT_DATE(), CURRENT_DATE Synonyms for CURDATE()
CURRENT_ROLE() Return the current active roles
CURRENT_TIME(), CURRENT_TIME Synonyms for CURTIME()
CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP Synonyms for NOW()
CURRENT_USER(), CURRENT_USER The authenticated user name and host name
CURTIME() Return the current time
DATABASE() Return the default (current) database name
DATE() Extract the date part of a date or datetime expression
DATE_ADD() Add time values (intervals) to a date value
DATE_FORMAT() Format date as speci^ed
DATE_SUB() Subtract a time value (interval) from a date
DATEDIFF() Subtract two dates
DAY() Synonym for DAYOFMONTH()
DAYNAME() Return the name of the weekday
DAYOFMONTH() Return the day of the month (0-31)
DAYOFWEEK() Return the weekday index of the argument
DAYOFYEAR() Return the day of the year (1-366)
DECODE() Decode a string encrypted using ENCODE()
DEFAULT() Return the default value for a table column
DEGREES() Convert radians to degrees
DENSE_RANK() Rank of current row within its partition, without gaps
DES_DECRYPT() Decrypt a string
DES_ENCRYPT() Encrypt a string
DIV Integer division
/ Division operator
ELT() Return string at index number
ENCODE() Encode a string
ENCRYPT() Encrypt a string
= Equal operator
<=> NULL-safe equal to operator
EXP() Raise to the power of
Return a string such that for every bit set in the value bits, you get an
EXPORT_SET()
on string and for every unset bit, you get an off string
EXTRACT() Extract part of a date
ExtractValue() Extract a value from an XML string using XPath notation
FIELD() Index (position) of ^rst argument in subsequent arguments
FIND_IN_SET() Index (position) of ^rst argument within second argument
FIRST_VALUE() Value of argument from ^rst row of window frame
FLOOR() Return the largest integer value not greater than the argument
FORMAT() Return a number formatted to speci^ed number of decimal places
FORMAT_BYTES() Convert byte count to value with units
FORMAT_PICO_TIME() Convert time in picoseconds to value with units
For a SELECT with a LIMIT clause, the number of rows that would be
FOUND_ROWS()
returned were there no LIMIT clause
FROM_BASE64() Decode base64 encoded string and return result
FROM_DAYS() Convert a day number to a date
FROM_UNIXTIME() Format Unix timestamp as a date
GeomCollection() Construct geometry collection from geometries
GeometryCollection() Construct geometry collection from geometries
GET_DD_COLUMN_PRIVILEGES() Internal use only
GET_DD_CREATE_OPTIONS() Internal use only
GET_DD_INDEX_SUB_PART_LENGTH() Internal use only
GET_FORMAT() Return a date format string
GET_LOCK() Get a named lock
> Greater than operator
>= Greater than or equal operator
GREATEST() Return the largest argument
GROUP_CONCAT() Return a concatenated string
GROUPING() Distinguish super-aggregate ROLLUP rows from regular rows
GTID_SUBSET() Return true if all GTIDs in subset are also in set; otherwise false.
GTID_SUBTRACT() Return all GTIDs in set that are not in subset.
HEX() Hexadecimal representation of decimal or string value
HOUR() Extract the hour
ICU_VERSION() ICU library version
IF() If/else construct
IFNULL() Null if/else construct
IN() Check whether a value is within a set of values
INET_ATON() Return the numeric value of an IP address
INET_NTOA() Return the IP address from a numeric value
INET6_ATON() Return the numeric value of an IPv6 address
INET6_NTOA() Return the IPv6 address from a numeric value
Insert substring at speci^ed position up to speci^ed number of
INSERT()
characters
INSTR() Return the index of the ^rst occurrence of substring
INTERNAL_AUTO_INCREMENT() Internal use only
INTERNAL_AVG_ROW_LENGTH() Internal use only
INTERNAL_CHECK_TIME() Internal use only
INTERNAL_CHECKSUM() Internal use only
INTERNAL_DATA_FREE() Internal use only
INTERNAL_DATA_LENGTH() Internal use only
INTERNAL_DD_CHAR_LENGTH() Internal use only
INTERNAL_GET_COMMENT_OR_ERROR() Internal use only
INTERNAL_GET_VIEW_WARNING_OR_ERROR() Internal use only
INTERNAL_INDEX_COLUMN_CARDINALITY() Internal use only
INTERNAL_INDEX_LENGTH() Internal use only
INTERNAL_KEYS_DISABLED() Internal use only
INTERNAL_MAX_DATA_LENGTH() Internal use only
INTERNAL_TABLE_ROWS() Internal use only
INTERNAL_UPDATE_TIME() Internal use only
INTERVAL() Return the index of the argument that is less than the ^rst argument
IS Test a value against a boolean
IS_FREE_LOCK() Whether the named lock is free
IS_IPV4() Whether argument is an IPv4 address
IS_IPV4_COMPAT() Whether argument is an IPv4-compatible address
IS_IPV4_MAPPED() Whether argument is an IPv4-mapped address
IS_IPV6() Whether argument is an IPv6 address
IS NOT Test a value against a boolean
IS NOT NULL NOT NULL value test
IS NULL NULL value test
IS_USED_LOCK() Whether the named lock is in use; return connection identi^er if true
IS_UUID() Whether argument is a valid UUID
ISNULL() Test whether the argument is NULL
JSON_ARRAY() Create JSON array
JSON_ARRAY_APPEND() Append data to JSON document
JSON_ARRAY_INSERT() Insert into JSON array
JSON_ARRAYAGG() Return result set as a single JSON array
Return value from JSON column after evaluating path; equivalent to
->
JSON_EXTRACT().
JSON_CONTAINS() Whether JSON document contains speci^c object at path
JSON_CONTAINS_PATH() Whether JSON document contains any data at path
JSON_DEPTH() Maximum depth of JSON document
JSON_EXTRACT() Return data from JSON document
Return value from JSON column after evaluating path and unquoting
->>
the result; equivalent to JSON_UNQUOTE(JSON_EXTRACT()).
JSON_INSERT() Insert data into JSON document
JSON_KEYS() Array of keys from JSON document
JSON_LENGTH() Number of elements in JSON document
Merge JSON documents, preserving duplicate keys. Deprecated
JSON_MERGE() (deprecated 8.0.3)
synonym for JSON_MERGE_PRESERVE()
JSON_MERGE_PATCH() Merge JSON documents, replacing values of duplicate keys
JSON_MERGE_PRESERVE() Merge JSON documents, preserving duplicate keys
JSON_OBJECT() Create JSON object
JSON_OBJECTAGG() Return result set as a single JSON object
JSON_PRETTY() Print a JSON document in human-readable format
JSON_QUOTE() Quote JSON document
JSON_REMOVE() Remove data from JSON document
JSON_REPLACE() Replace values in JSON document
JSON_SEARCH() Path to value within JSON document
JSON_SET() Insert data into JSON document
Freed space within binary representation of a JSON column value
JSON_STORAGE_FREE()
following a partial update
JSON_STORAGE_SIZE() Space used for storage of binary representation of a JSON document
JSON_TABLE() Return data from a JSON expression as a relational table
JSON_TYPE() Type of JSON value
JSON_UNQUOTE() Unquote JSON value
JSON_VALID() Whether JSON value is valid
LAG() Value of argument from row lagging current row within partition
LAST_DAY Return the last day of the month for the argument
LAST_INSERT_ID() Value of the AUTOINCREMENT column for the last INSERT
LAST_VALUE() Value of argument from last row of window frame
LCASE() Synonym for LOWER()
LEAD() Value of argument from row leading current row within partition
LEAST() Return the smallest argument
LEFT() Return the leftmost number of characters as speci^ed
<< Left shift
LENGTH() Return the length of a string in bytes
< Less than operator
<= Less than or equal operator
LIKE Simple pattern matching
LineString() Construct LineString from Point values
LN() Return the natural logarithm of the argument
LOAD_FILE() Load the named ^le
LOCALTIME(), LOCALTIME Synonym for NOW()
LOCALTIMESTAMP, LOCALTIMESTAMP() Synonym for NOW()
LOCATE() Return the position of the ^rst occurrence of substring
LOG() Return the natural logarithm of the ^rst argument
LOG10() Return the base-10 logarithm of the argument
LOG2() Return the base-2 logarithm of the argument
LOWER() Return the argument in lowercase
LPAD() Return the string argument, left-padded with the speci^ed string
LTRIM() Remove leading spaces
Return a set of comma-separated strings that have the corresponding
MAKE_SET()
bit in bits set
MAKEDATE() Create a date from the year and day of year
MAKETIME() Create time from hour, minute, second
Block until the slave has read and applied all updates up to the
MASTER_POS_WAIT()
speci^ed position
MATCH Perform full-text search
MAX() Return the maximum value
MBRContains() Whether MBR of one geometry contains MBR of another
MBRCoveredBy() Whether one MBR is covered by another
MBRCovers() Whether one MBR covers another
MBRDisjoint() Whether MBRs of two geometries are disjoint
MBREquals() Whether MBRs of two geometries are equal
MBRIntersects() Whether MBRs of two geometries intersect
MBROverlaps() Whether MBRs of two geometries overlap
MBRTouches() Whether MBRs of two geometries touch
MBRWithin() Whether MBR of one geometry is within MBR of another
MD5() Calculate MD5 checksum
MICROSECOND() Return the microseconds from argument
MID() Return a substring starting from the speci^ed position
MIN() Return the minimum value
- Minus operator
MINUTE() Return the minute from the argument
MOD() Return the remainder
%, MOD Modulo operator
MONTH() Return the month from the date passed
MONTHNAME() Return the name of the month
MultiLineString() Contruct MultiLineString from LineString values
MultiPoint() Construct MultiPoint from Point values
MultiPolygon() Construct MultiPolygon from Polygon values
NAME_CONST() Cause the column to have the given name
NOT, ! Negates value
NOT BETWEEN ... AND ... Check whether a value is not within a range of values
!=, <> Not equal operator
NOT IN() Check whether a value is not within a set of values
NOT LIKE Negation of simple pattern matching
NOT REGEXP Negation of REGEXP
NOW() Return the current date and time
NTH_VALUE() Value of argument from N-th row of window frame
NTILE() Bucket number of current row within its partition.
NULLIF() Return NULL if expr1 = expr2
OCT() Return a string containing octal representation of a number
OCTET_LENGTH() Synonym for LENGTH()
||, OR Logical OR
ORD() Return character code for leftmost character of the argument
PASSWORD() Calculate and return a password string
PERCENT_RANK() Percentage rank value
PERIOD_ADD() Add a period to a year-month
PERIOD_DIFF() Return the number of months between periods
PI() Return the value of pi
+ Addition operator
Point() Construct Point from coordinates
Polygon() Construct Polygon from LineString arguments
POSITION() Synonym for LOCATE()
POW() Return the argument raised to the speci^ed power
POWER() Return the argument raised to the speci^ed power
PS_CURRENT_THREAD_ID() Performance Schema thread ID for current thread
PS_THREAD_ID() Performance Schema thread ID for given thread
QUARTER() Return the quarter from a date argument
QUOTE() Escape the argument for use in an SQL statement
RADIANS() Return argument converted to radians
RAND() Return a random joating-point value
RANDOM_BYTES() Return a random byte vector
RANK() Rank of current row within its partition, with gaps
REGEXP Whether string matches regular expression
REGEXP_INSTR() Starting index of substring matching regular expression
REGEXP_LIKE() Whether string matches regular expression
REGEXP_REPLACE() Replace substrings matching regular expression
REGEXP_SUBSTR() Return substring matching regular expression
RELEASE_ALL_LOCKS() Release all current named locks
RELEASE_LOCK() Release the named lock
REPEAT() Repeat a string the speci^ed number of times
REPLACE() Replace occurrences of a speci^ed string
REVERSE() Reverse the characters in a string
RIGHT() Return the speci^ed rightmost number of characters
>> Right shift
RLIKE Whether string matches regular expression
ROLES_GRAPHML() Return a GraphML document representing memory role subgraphs
ROUND() Round the argument
ROW_COUNT() The number of rows updated
ROW_NUMBER() Number of current row within its partition
RPAD() Append string the speci^ed number of times
RTRIM() Remove trailing spaces
SCHEMA() Synonym for DATABASE()
SEC_TO_TIME() Converts seconds to 'HH:MM:SS' format
SECOND() Return the second (0-59)
SESSION_USER() Synonym for USER()
SHA1(), SHA() Calculate an SHA-1 160-bit checksum
SHA2() Calculate an SHA-2 checksum
SIGN() Return the sign of the argument
SIN() Return the sine of the argument
SLEEP() Sleep for a number of seconds
SOUNDEX() Return a soundex string
SOUNDS LIKE Compare sounds
SPACE() Return a string of the speci^ed number of spaces
SQRT() Return the square root of the argument
ST_Area() Return Polygon or MultiPolygon area
ST_AsBinary(), ST_AsWKB() Convert from internal geometry format to WKB
ST_AsGeoJSON() Generate GeoJSON object from geometry
ST_AsText(), ST_AsWKT() Convert from internal geometry format to WKT
ST_Buffer() Return geometry of points within given distance from geometry
ST_Buffer_Strategy() Produce strategy option for ST_Buffer()
ST_Centroid() Return centroid as a point
ST_Contains() Whether one geometry contains another
ST_ConvexHull() Return convex hull of geometry
ST_Crosses() Whether one geometry crosses another
ST_Difference() Return point set difference of two geometries
ST_Dimension() Dimension of geometry
ST_Disjoint() Whether one geometry is disjoint from another
ST_Distance() The distance of one geometry from another
ST_Distance_Sphere() Minimum distance on earth between two geometries
ST_EndPoint() End Point of LineString
ST_Envelope() Return MBR of geometry
ST_Equals() Whether one geometry is equal to another
ST_ExteriorRing() Return exterior ring of Polygon
ST_GeoHash() Produce a geohash value
ST_GeomCollFromText(), ST_GeometryCollecti
Return geometry collection from WKT
onFromText(), ST_GeomCollFromTxt()

ST_GeomCollFromWKB(), ST_GeometryCollectio
Return geometry collection from WKB
nFromWKB()
ST_GeometryN() Return N-th geometry from geometry collection
ST_GeometryType() Return name of geometry type
ST_GeomFromGeoJSON() Generate geometry from GeoJSON object
ST_GeomFromText(), ST_GeometryFromText() Return geometry from WKT
ST_GeomFromWKB(), ST_GeometryFromWKB() Return geometry from WKB
ST_InteriorRingN() Return N-th interior ring of Polygon
ST_Intersection() Return point set intersection of two geometries
ST_Intersects() Whether one geometry intersects another
ST_IsClosed() Whether a geometry is closed and simple
ST_IsEmpty() Placeholder function
ST_IsSimple() Whether a geometry is simple
ST_IsValid() Whether a geometry is valid
ST_LatFromGeoHash() Return latitude from geohash value
ST_Latitude() Return latitude of Point
ST_Length() Return length of LineString
ST_LineFromText(), ST_LineStringFromText() Construct LineString from WKT

ST_LineFromWKB(), ST_LineStringFromWKB() Construct LineString from WKB


ST_LongFromGeoHash() Return longitude from geohash value
ST_Longitude() Return longitude of Point
ST_MakeEnvelope() Rectangle around two points
ST_MLineFromText(), ST_MultiLineStringFrom
Construct MultiLineString from WKT
Text()

ST_MLineFromWKB(), ST_MultiLineStringFromW
Construct MultiLineString from WKB
KB()

ST_MPointFromText(), ST_MultiPointFromText
Construct MultiPoint from WKT
()

ST_MPointFromWKB(), ST_MultiPointFromWKB() Construct MultiPoint from WKB

ST_MPolyFromText(), ST_MultiPolygonFromTex
Construct MultiPolygon from WKT
t()

ST_MPolyFromWKB(), ST_MultiPolygonFromWKB(
Construct MultiPolygon from WKB
)

ST_NumGeometries() Return number of geometries in geometry collection


ST_NumInteriorRing(), ST_NumInteriorRings(
Return number of interior rings in Polygon
)

ST_NumPoints() Return number of points in LineString


ST_Overlaps() Whether one geometry overlaps another
ST_PointFromGeoHash() Convert geohash value to POINT value
ST_PointFromText() Construct Point from WKT
ST_PointFromWKB() Construct Point from WKB

ST_PointN() Return N-th point from LineString


ST_PolyFromText(), ST_PolygonFromText() Construct Polygon from WKT
ST_PolyFromWKB(), ST_PolygonFromWKB() Construct Polygon from WKB
ST_Simplify() Return simpli^ed geometry
ST_SRID() Return spatial reference system ID for geometry
ST_StartPoint() Start Point of LineString
ST_SwapXY() Return argument with X/Y coordinates swapped
ST_SymDifference() Return point set symmetric difference of two geometries
ST_Touches() Whether one geometry touches another
ST_Transform() Transform coordinates of geometry
ST_Union() Return point set union of two geometries
ST_Validate() Return validated geometry
ST_Within() Whether one geometry is within another
ST_X() Return X coordinate of Point
ST_Y() Return Y coordinate of Point
STATEMENT_DIGEST() Compute statement digest hash value
STATEMENT_DIGEST_TEXT() Compute normalized statement digest
STD() Return the population standard deviation
STDDEV() Return the population standard deviation
STDDEV_POP() Return the population standard deviation
STDDEV_SAMP() Return the sample standard deviation
STR_TO_DATE() Convert a string to a date
STRCMP() Compare two strings
SUBDATE() Synonym for DATE_SUB() when invoked with three arguments
SUBSTR() Return the substring as speci^ed
SUBSTRING() Return the substring as speci^ed
Return a substring from a string before the speci^ed number of
SUBSTRING_INDEX()
occurrences of the delimiter
SUBTIME() Subtract times
SUM() Return the sum
SYSDATE() Return the time at which the function executes
SYSTEM_USER() Synonym for USER()
TAN() Return the tangent of the argument
TIME() Extract the time portion of the expression passed
TIME_FORMAT() Format as time
TIME_TO_SEC() Return the argument converted to seconds
TIMEDIFF() Subtract time
* Multiplication operator
With a single argument, this function returns the date or datetime
TIMESTAMP() expression; with two arguments, the sum of the arguments

TIMESTAMPADD() Add an interval to a datetime expression


TIMESTAMPDIFF() Subtract an interval from a datetime expression
TO_BASE64() Return the argument converted to a base-64 string
TO_DAYS() Return the date argument converted to days
Return the date or datetime argument converted to seconds since Year
TO_SECONDS()
0
TRIM() Remove leading and trailing spaces
TRUNCATE() Truncate to speci^ed number of decimal places
UCASE() Synonym for UPPER()
- Change the sign of the argument
UNCOMPRESS() Uncompress a string compressed
UNCOMPRESSED_LENGTH() Return the length of a string before compression
UNHEX() Return a string containing hex representation of a number
          Andrew Francisco
UNIX_TIMESTAMP() Return a Unix timestamp
UpdateXML() Return replaced XML fragment
UPPER() Convert toDashboard
uppercase Course Options Members-Only Forum About

USER() The user name and host name provided by the client
UTC_DATE() Return the current UTC date
UTC_TIME() Return the current UTC time
UTC_TIMESTAMP() Return the current UTC date and time
UUID() Return a Universal Unique Identi^er (UUID)
UUID_SHORT() Return an integer-valued universal identi^er
UUID_TO_BIN() Convert string UUID to binary
VALIDATE_PASSWORD_STRENGTH() Determine strength of password
VALUES() De^ne the values to be used during an INSERT
VAR_POP() Return the population standard variance
VAR_SAMP() Return the sample variance
VARIANCE() Return the population standard variance
VERSION() Return a string that indicates the MySQL server version
WAIT_FOR_EXECUTED_GTID_SET() Wait until the given GTIDs have executed on slave.
WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS() Wait until the given GTIDs have executed on slave.
WEEK() Return the week number
WEEKDAY() Return the weekday index
WEEKOFYEAR() Return the calendar week of the date (1-53)
WEIGHT_STRING() Return the weight string for a string
XOR Logical XOR
YEAR() Return the year
YEARWEEK() Return the year and week

◀︎ Note on This Reference Section Type Conversion in Expression Evaluation Reference ▶︎


"Success occurs when opportunity meets preparation."


      

You are logged in as Andrew Francisco (Log out)

Copyright © CodingNomads 2022


Type Conversion in Expression
Evaluation Reference
Sourced from MySQL Docs
here: https://dev.mysql.com/doc/refman/8.0/en/type-conversion.html

When an operator is used with operands of different types, type conversion


occurs to make the operands compatible. Some conversions occur implicitly.
For example, MySQL automatically converts strings to numbers as
necessary, and vice versa.

mysql> SELECT 1+'1';


-> 2
mysql> SELECT CONCAT(2,' test');
-> '2 test'

It is also possible to convert a number to a string explicitly using


the CAST() function. Conversion occurs implicitly with the CONCAT() function
because it expects string arguments.

mysql> SELECT 38.8, CAST(38.8 AS CHAR);


-> 38.8, '38.8'
mysql> SELECT 38.8, CONCAT(38.8);
-> 38.8, '38.8'

See later in this section for information about the character set of implicit
number-to-string conversions, and for modified rules that apply to CREATE
TABLE ... SELECT statements.

The following rules describe how conversion occurs for comparison


operations:

If one or both arguments are NULL, the result of the comparison is NULL,
except for the NULL-safe <=> equality comparison operator. For NULL <=>
NULL, the result is true. No conversion is needed.

If both arguments in a comparison operation are strings, they are


compared as strings.

If both arguments are integers, they are compared as integers.

Hexadecimal values are treated as binary strings if not compared to a


number.

If one of the arguments is a TIMESTAMP or DATETIME column and the


other argument is a constant, the constant is converted to a timestamp
before the comparison is performed. This is done to be more ODBC-
friendly. This is not done for the arguments to IN(). To be safe, always
use complete datetime, date, or time strings when doing comparisons.
For example, to achieve best results when using BETWEEN with date or
time values, use CAST() to explicitly convert the values to the desired
data type.

A single-row subquery from a table or tables is not considered a


constant. For example, if a subquery returns an integer to be compared
to a DATETIME value, the comparison is done as two integers. The
integer is not converted to a temporal value. To compare the operands
as DATETIME values, use CAST() to explicitly convert the subquery value
to DATETIME.

If one of the arguments is a decimal value, comparison depends on the


other argument. The arguments are compared as decimal values if the
other argument is a decimal or integer value, or as floating-point values
if the other argument is a floating-point value.
In all other cases, the arguments are compared as floating-point (real)
numbers.
Operators Reference
Sourced from MySQL Docs
here: https://dev.mysql.com/doc/refman/8.0/en/non-typed-operators.html
Name Description
AND, && Logical AND
Assign a value (as part of a SET statement, or as
=
part of the SET clause in an UPDATEstatement)
:= Assign a value
Check whether a value is within a range of
BETWEEN ... AND ...
values
BINARY Cast a string to a binary string
& Bitwise AND
~ Bitwise inversion
| Bitwise OR
^ Bitwise XOR
CASE Case operator
DIV Integer division
/ Division operator
= Equal operator
<=> NULL-safe equal to operator
> Greater than operator
>= Greater than or equal operator
IS Test a value against a boolean
IS NOT Test a value against a boolean
IS NOT NULL NOT NULL value test
IS NULL NULL value test
Return value from JSON column after evaluating
->
path; equivalent to JSON_EXTRACT().
Return value from JSON column after evaluating
->> path and unquoting the result; equivalent to
JSON_UNQUOTE(JSON_EXTRACT()).
<< Left shift
< Less than operator
<= Less than or equal operator
LIKE Simple pattern matching
- Minus operator
%, MOD Modulo operator
NOT, ! Negates value
Check whether a value is not within a range of
NOT BETWEEN ... AND ...
values
!=, <> Not equal operator
NOT LIKE Negation of simple pattern matching
NOT REGEXP Negation of REGEXP
||, OR Logical OR
+ Addition operator
REGEXP Whether string matches regular expression
>> Right shift
RLIKE Whether string matches regular expression
SOUNDS LIKE Compare sounds
* Multiplication operator
- Change the sign of the argument
XOR Logical XOR
Comparison Operators Reference
Name Description
Check whether a value is within a range of
BETWEEN ... AND ...
values
COALESCE() Return the first non-NULL argument
= Equal operator
<=> NULL-safe equal to operator
> Greater than operator
>= Greater than or equal operator
GREATEST() Return the largest argument
IN() Check whether a value is within a set of values
Return the index of the argument that is less
INTERVAL()
than the first argument
IS Test a value against a boolean
IS NOT Test a value against a boolean
IS NOT NULL NOT NULL value test
IS NULL NULL value test
ISNULL() Test whether the argument is NULL
LEAST() Return the smallest argument
< Less than operator
<= Less than or equal operator
LIKE Simple pattern matching
Check whether a value is not within a range of
NOT BETWEEN ... AND ...
values
!=, <> Not equal operator
Check whether a value is not within a set of
NOT IN()
values
NOT LIKE Negation of simple pattern matching
STRCMP() Compare two strings
Comparison operations result in a value of 1 (TRUE), 0 (FALSE), or NULL. These
operations work for both numbers and strings. Strings are automatically
converted to numbers and numbers to strings as necessary.

The following relational comparison operators can be used to compare not


only scalar operands, but row operands:

The descriptions for those operators later in this section detail how they
work with row operands. For additional examples of row comparisons in the
context of row subqueries, see Section 13.2.11.5, “Row Subqueries”.

Some of the functions in this section return values other


than 1 (TRUE), 0 (FALSE), or NULL. LEAST() and GREATEST() are examples of
such functions; Section 12.2, “Type Conversion in Expression Evaluation”,
describes the rules for comparison operations performed by these and
similar functions for determining their return values.

Note

In previous versions of MySQL, when evaluating an expression


containing LEAST() or GREATEST(), the server attempted to guess the context
in which the function was used, and to coerce the function's arguments to
the data type of the expression as a whole. For example, the arguments
to LEAST("11", "45", "2") are evaluated and sorted as strings, so that this
expression returns "11". In MySQL 8.0.3 and earlier, when evaluating the
expression LEAST("11", "45", "2") + 0, the server converted the
arguments to integers (anticipating the addition of integer 0 to the result)
before sorting them, thus returning 2.

Beginning with MySQL 8.0.4, the server no longer attempts to infer context
in this fashion. Instead, the function is executed using the arguments as
provided, performing data type conversions to one or more of the arguments
if and only if they are not all of the same type. Any type coercion mandated
by an expression that makes use of the return value is now performed
following function execution. This means that, in MySQl 8.0.4 and
later, LEAST("11", "45", "2") + 0 evaluates to "11" + 0 and thus to integer
11. (Bug #83895, Bug #25123839)

To convert a value to a specific type for comparison purposes, you can use
the CAST() function. String values can be converted to a different character
set using CONVERT(). See Section 12.10, “Cast Functions and Operators”.

By default, string comparisons are not case-sensitive and use the current
character set. The default is utf8mb4.

Equal:

mysql> SELECT 1 = 0;
-> 0
mysql> SELECT '0' = 0;
-> 1
mysql> SELECT '0.0' = 0;
-> 1
mysql> SELECT '0.01' = 0;
-> 0
mysql> SELECT '.01' = 0.01;
-> 1

For row comparisons, (a, b) = (x, y) is equivalent to:

(a = x) AND (b = y)
<=>

NULL-safe equal. This operator performs an equality comparison like


the = operator, but returns 1 rather than NULL if both operands are NULL,
and 0 rather than NULL if one operand is NULL.

The <=> operator is equivalent to the standard SQL IS NOT DISTINCT


FROM operator.

mysql> SELECT 1 <=> 1, NULL <=> NULL, 1 <=> NULL;


-> 1, 1, 0
mysql> SELECT 1 = 1, NULL = NULL, 1 = NULL;
-> 1, NULL, NULL

For row comparisons, (a, b) <=> (x, y) is equivalent to:

(a <=> x) AND (b <=> y)

<>, !=

Not equal:

mysql> SELECT '.01' <> '0.01';


-> 1
mysql> SELECT .01 <> '0.01';
-> 0
mysql> SELECT 'zapp' <> 'zappp';
-> 1

For row comparisons, (a, b) <> (x, y) and (a, b) != (x, y) are
equivalent to:
(a <> x) OR (b <> y)

<=

Less than or equal:

mysql> SELECT 0.1 <= 2;


-> 1

For row comparisons, (a, b) <= (x, y) is equivalent to:

(a < x) OR ((a = x) AND (b <= y))

<

Less than:

mysql> SELECT 2 < 2;


-> 0

For row comparisons, (a, b) < (x, y) is equivalent to:

(a < x) OR ((a = x) AND (b < y))

>=

Greater than or equal:


mysql> SELECT 2 >= 2;
-> 1

For row comparisons, (a, b) >= (x, y) is equivalent to:

(a > x) OR ((a = x) AND (b >= y))

>

Greater than:

mysql> SELECT 2 > 2;


-> 0

For row comparisons, (a, b) > (x, y) is equivalent to:

(a > x) OR ((a = x) AND (b > y))

Tests a value against a boolean value, where boolean_value can


be TRUE, FALSE, or UNKNOWN.

mysql> SELECT 1 IS TRUE, 0 IS FALSE, NULL IS UNKNOWN;


-> 1, 1, 1

IS NOT boolean_value

Tests a value against a boolean value, where boolean_value can


be TRUE, FALSE, or UNKNOWN.
mysql> SELECT 1 IS NOT UNKNOWN, 0 IS NOT UNKNOWN, NULL IS NOT UNKNOWN;
-> 1, 1, 0

IS NULL

Tests whether a value is NULL.

mysql> SELECT 1 IS NULL, 0 IS NULL, NULL IS NULL;


-> 0, 0, 1

To work well with ODBC programs, MySQL supports the following extra
features when using IS NULL:

If sql_auto_is_null variable is set to 1, then after a statement that


successfully inserts an automatically
generated AUTO_INCREMENTvalue, you can find that value by issuing
a statement of the following form:

SELECT * FROM tbl_name WHERE auto_col IS NULL

The behavior of retrieving an AUTO_INCREMENT value by using an IS


NULL comparison can be disabled by setting sql_auto_is_null =
0. See Section 5.1.8, “Server System Variables”.

The default value of sql_auto_is_null is 0.

If the statement returns a row, the value returned is the same as if


you invoked the LAST_INSERT_ID() function. For details, including
the return value after a multiple-row insert, see Section 12.15,
“Information Functions”. If no AUTO_INCREMENT value was
successfully inserted, the SELECT statement returns no row.

For DATE and DATETIME columns that are declared as NOT NULL, you
can find the special date '0000-00-00' by using a statement like
this:

SELECT * FROM tbl_name WHERE date_column IS NULL

See Obtaining Auto-Increment Values, and the description for


the FLAG_AUTO_IS_NULL option at Connector/ODBC Connection
Parameters.

This is needed to get some ODBC applications to work because


ODBC does not support a '0000-00-00' date value.

IS NOT NULL

Tests whether a value is not NULL.

mysql> SELECT 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL;


-> 1, 1, 0

expr BETWEEN min AND max

If expr is greater than or equal to min and expr is less than or equal
to max, BETWEEN returns 1, otherwise it returns 0. This is equivalent to the
expression (min <= expr AND expr <= max) if all the arguments are of
the same type. Otherwise type conversion takes place according to the
rules described in Section 12.2, “Type Conversion in Expression
Evaluation”, but applied to all the three arguments.
mysql> SELECT 2 BETWEEN 1 AND 3, 2 BETWEEN 3 and 1;
-> 1, 0
mysql> SELECT 1 BETWEEN 2 AND 3;
-> 0
mysql> SELECT 'b' BETWEEN 'a' AND 'c';
-> 1
mysql> SELECT 2 BETWEEN 2 AND '3';
-> 1
mysql> SELECT 2 BETWEEN 2 AND 'x-3';
-> 0

For best results when using BETWEEN with date or time values,
use CAST() to explicitly convert the values to the desired data type.
Examples: If you compare a DATETIME to two DATE values, convert
the DATE values to DATETIME values. If you use a string constant such
as '2001-1-1' in a comparison to a DATE, cast the string to a DATE.

expr NOT BETWEEN min AND max

This is the same as NOT (expr BETWEEN min AND max).

COALESCE(value,...)

Returns the first non-NULL value in the list, or NULL if there are no non-
NULL values.

The return type of COALESCE() is the aggregated type of the argument


types.

mysql> SELECT COALESCE(NULL,1);


-> 1
mysql> SELECT COALESCE(NULL,NULL,NULL);
-> NULL
GREATEST(value1,value2,...)

With two or more arguments, returns the largest (maximum-valued)


argument. The arguments are compared using the same rules as
for LEAST().

mysql> SELECT GREATEST(2,0);


-> 2
mysql> SELECT GREATEST(34.0,3.0,5.0,767.0);
-> 767.0
mysql> SELECT GREATEST('B','A','C');
-> 'C'

GREATEST() returns NULL if any argument is NULL.

expr IN (value,...)

Returns 1 if expr is equal to any of the values in the IN list, else


returns 0. If all values are constants, they are evaluated according to the
type of expr and sorted. The search for the item then is done using a
binary search. This means IN is very quick if the IN value list consists
entirely of constants. Otherwise, type conversion takes place according
to the rules described in Section 12.2, “Type Conversion in Expression
Evaluation”, but applied to all the arguments.

mysql> SELECT 2 IN (0,3,5,7);


-> 0
mysql> SELECT 'wefwf' IN ('wee','wefwf','weg');
-> 1

IN can be used to compare row constructors:


mysql> SELECT (3,4) IN ((1,2), (3,4));
-> 1
mysql> SELECT (3,4) IN ((1,2), (3,5));
-> 0

You should never mix quoted and unquoted values in an IN list because
the comparison rules for quoted values (such as strings) and unquoted
values (such as numbers) differ. Mixing types may therefore lead to
inconsistent results. For example, do not write an IN expression like this:

SELECT val1 FROM tbl1 WHERE val1 IN (1,2,'a');

Instead, write it like this:

SELECT val1 FROM tbl1 WHERE val1 IN ('1','2','a');

The number of values in the IN list is only limited by


the max_allowed_packet value.

To comply with the SQL standard, IN returns NULL not only if the
expression on the left hand side is NULL, but also if no match is found in
the list and one of the expressions in the list is NULL.

IN() syntax can also be used to write certain types of subqueries.


See Section 13.2.11.3, “Subqueries with ANY, IN, or SOME”.

expr NOT IN (value,...)

This is the same as NOT (expr IN (value,...)).


ISNULL(expr)

If expr is NULL, ISNULL() returns 1, otherwise it returns 0.

mysql> SELECT ISNULL(1+1);


-> 0
mysql> SELECT ISNULL(1/0);
-> 1

ISNULL() can be used instead of = to test whether a value is NULL.


(Comparing a value to NULL using = always yields NULL.)

The ISNULL() function shares some special behaviors with the IS


NULL comparison operator. See the description of IS NULL.

INTERVAL(N,N1,N2,N3,...)

Returns 0 if N < N1, 1 if N < N2 and so on or -1 if N is NULL. All arguments


are treated as integers. It is required that N1 < N2 < N3 < ... < Nn for this
function to work correctly. This is because a binary search is used (very
fast).

mysql> SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200);


-> 3
mysql> SELECT INTERVAL(10, 1, 10, 100, 1000);
-> 2
mysql> SELECT INTERVAL(22, 23, 30, 44, 200);
-> 0

LEAST(value1,value2,...)

With two or more arguments, returns the smallest (minimum-valued)


argument. The arguments are compared using the following rules:

If any argument is NULL, the result is NULL. No comparison is


needed.

If all arguments are integer-valued, they are compared as integers.

If at least one argument is double precision, they are compared as


double-precision values. Otherwise, if at least one argument is
aDECIMAL value, they are compared as DECIMAL values.

If the arguments comprise a mix of numbers and strings, they are


compared as strings.

If any argument is a nonbinary (character) string, the arguments


are compared as nonbinary strings.

In all other cases, the arguments are compared as binary strings.

The return type of LEAST() is the aggregated type of the comparison


argument types.

mysql> SELECT LEAST(2,0);


-> 0
mysql> SELECT LEAST(34.0,3.0,5.0,767.0);
-> 3.0
mysql> SELECT LEAST('B','A','C');
-> 'A'
Logical Operators Reference
In SQL, all logical operators evaluate to TRUE, FALSE, or NULL (UNKNOWN). In
MySQL, these are implemented as 1 (TRUE), 0 (FALSE), and NULL. Most of this
is common to different SQL database servers, although some servers may
return any nonzero value for TRUE.

MySQL evaluates any nonzero, non-NULL value to TRUE. For example, the
following statements all assess to TRUE:

mysql> SELECT 10 IS TRUE;

-> 1
mysql> SELECT -10 IS TRUE;
-> 1
mysql> SELECT 'string' IS NOT NULL;
-> 1

NOT, !

Logical NOT. Evaluates to 1 if the operand is 0, to 0 if the operand is


nonzero, and NOT NULL returns NULL.

The last example produces 1 because the expression evaluates the


same way as (!1)+1.

mysql> SELECT NOT 10;


-> 0
mysql> SELECT NOT 0;
-> 1
mysql> SELECT NOT NULL;
-> NULL
mysql> SELECT ! (1+1);
-> 0
mysql> SELECT ! 1+1;
-> 1

AND, &&

Logical AND. Evaluates to 1 if all operands are nonzero and not NULL, to 0 if
one or more operands are 0, otherwise NULL is returned.

mysql> SELECT 1 AND 1;


-> 1
mysql> SELECT 1 AND 0;
-> 0
mysql> SELECT 1 AND NULL;
-> NULL
mysql> SELECT 0 AND NULL;
-> 0
mysql> SELECT NULL AND 0;
-> 0

OR, ||

Logical OR. When both operands are non-NULL, the result is 1 if any
operand is nonzero, and 0 otherwise. With a NULL operand, the result
is 1if the other operand is nonzero, and NULL otherwise. If both operands
are NULL, the result is NULL.

mysql> SELECT 1 OR 1;
-> 1
mysql> SELECT 1 OR 0;
-> 1
mysql> SELECT 0 OR 0;
-> 0
mysql> SELECT 0 OR NULL;
-> NULL
mysql> SELECT 1 OR NULL;
-> 1

XOR

Logical XOR. Returns NULL if either operand is NULL. For non-


NULL operands, evaluates to 1 if an odd number of operands is nonzero,
otherwise 0 is returned.

a XOR b is mathematically equal to (a AND (NOT b)) OR ((NOT a) and


b).

mysql> SELECT 1 XOR 1;


-> 0
mysql> SELECT 1 XOR 0;
-> 1
mysql> SELECT 1 XOR NULL;
-> NULL
mysql> SELECT 1 XOR 1 XOR 1;
-> 1
Control Flow Functions Reference
CASE value WHEN [compare_value] THEN result [WHEN
[compare_value] THEN result ...] [ELSE result] END

CASE WHEN [condition] THEN result [WHEN [condition]


THEN result ...] [ELSE result] END

The first CASE syntax returns the result for the


first value=compare_value comparison that is true. The second syntax
returns the result for the first condition that is true. If no comparison or
condition is true, the result after ELSE is returned, or NULL if there is
no ELSE part.

Note

The syntax of the CASE expr described here differs slightly from that of
the SQL CASE statement described in Section 13.6.5.1, “CASE Syntax”,
for use inside stored programs. The CASE statement cannot have
an ELSE NULL clause, and it is terminated with END CASE instead of END.

The return type of a CASE expression result is the aggregated type of all
result values:

If all types are numeric, the aggregated type is also numeric:

If at least one argument is double precision, the result is


double precision.

Otherwise, if at least one argument is DECIMAL, the result


is DECIMAL.

Otherwise, the result is an integer type (with one exception):


If all integer types are all signed or all unsigned, the result
is the same sign and the precision is the highest of all
specified integer types (that
is, TINYINT, SMALLINT, MEDIUMINT, INT, or BIGINT).

If there is a combination of signed and unsigned integer


types, the result is signed and the precision may be
higher. For example, if the types are signed INT and
unsigned INT, the result is signed BIGINT.

The exception is unsigned BIGINT combined with any


signed integer type. The result is DECIMAL with sufficient
precision and scale 0.

If all types are BIT, the result is BIT. Otherwise, BIT arguments are
treated similar to BIGINT.

If all types are YEAR, the result is YEAR. Otherwise, YEAR arguments
are treated similar to INT.

If all types are character string (CHAR or VARCHAR), the result


is VARCHAR with maximum length determined by the longest
character length of the operands.

If all types are character or binary string, the result is VARBINARY.

SET and ENUM are treated similar to VARCHAR; the result is VARCHAR.

If all types are JSON, the result is JSON.

If all types are temporal, the result is temporal:

If all types are GEOMETRY, the result is GEOMETRY.

If any type is BLOB, the result is BLOB.


For all other type combinations, the result is VARCHAR.

Literal NULL operands are ignored for type aggregation.

mysql> SELECT CASE 1 WHEN 1 THEN 'one'


-> WHEN 2 THEN 'two' ELSE 'more' END;
-> 'one'
mysql> SELECT CASE WHEN 1>0 THEN 'true' ELSE 'false' END;
-> 'true'
mysql> SELECT CASE BINARY 'B'
-> WHEN 'a' THEN 1 WHEN 'b' THEN 2 END;
-> NULL

IF(expr1,expr2,expr3)

If expr1 is TRUE (expr1 <> 0 and expr1 <> NULL), IF() returns expr2.
Otherwise, it returns expr3.

Note

There is also an IF statement, which differs from


the IF() function described here. See Section 13.6.5.2, “IF Syntax”.

If only one of expr2 or expr3 is explicitly NULL, the result type of


the IF() function is the type of the non-NULL expression.

The default return type of IF() (which may matter when it is stored into
a temporary table) is calculated as follows:

If expr2 or expr3 produce a string, the result is a string.

If expr2 and expr3 are both strings, the result is case-sensitive if


either string is case sensitive.
If expr2 or expr3 produce a floating-point value, the result is a
floating-point value.

If expr2 or expr3 produce an integer, the result is an integer.

mysql> SELECT IF(1>2,2,3);


-> 3
mysql> SELECT IF(1<2,'yes','no');
-> 'yes'
mysql> SELECT IF(STRCMP('test','test1'),'no','yes');
-> 'no'

IFNULL(expr1,expr2)

If expr1 is not NULL, IFNULL() returns expr1; otherwise it returns expr2.

The default return type of IFNULL(expr1,expr2) is the more “general” of


the two expressions, in the order STRING, REAL, or INTEGER. Consider the
case of a table based on expressions or where MySQL must internally
store a value returned by IFNULL() in a temporary table:

mysql> CREATE TABLE tmp SELECT IFNULL(1,'test') AS test;


mysql> DESCRIBE tmp;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| test | varbinary(4) | NO | | | |
+-------+--------------+------+-----+---------+-------+

In this example, the type of the test column is VARBINARY(4) (a string


type).
mysql> SELECT IFNULL(1,0);
-> 1
mysql> SELECT IFNULL(NULL,10);
-> 10
mysql> SELECT IFNULL(1/0,10);
-> 10
mysql> SELECT IFNULL(1/0,'yes');
-> 'yes'

NULLIF(expr1,expr2)

Returns NULL if expr1 = expr2 is true, otherwise returns expr1. This is


the same as CASE WHEN expr1 = expr2 THEN NULL ELSE expr1END.

The return value has the same type as the first argument.

mysql> SELECT NULLIF(1,1);


-> NULL
mysql> SELECT NULLIF(1,2);
-> 1
          Andrew Francisco

Dashboard Course Options Members-Only Forum About

 Dashboard / My courses / SQL & Databases / Sections / 7) Extended MySQL Functions Reference
/ String Functions Reference

String Functions Reference

Sourced from MySQL Docs here: https://dev.mysql.com/doc/refman/8.0/en/string-functions.html

Name Description
ASCII() Return numeric value of left-most character
BIN() Return a string containing binary representation of a number
BIT_LENGTH() Return length of argument in bits
CHAR() Return the character for each integer passed
CHAR_LENGTH() Return number of characters in argument
CHARACTER_LENGTH() Synonym for CHAR_LENGTH()
CONCAT() Return concatenated string
CONCAT_WS() Return concatenate with separator
ELT() Return string at index number
Return a string such that for every bit set in the value bits, you get an
EXPORT_SET()
on string and for every unset bit, you get an off string
FIELD() Index (position) of Urst argument in subsequent arguments
FIND_IN_SET() Index (position) of Urst argument within second argument
FORMAT() Return a number formatted to speciUed number of decimal places
FROM_BASE64() Decode base64 encoded string and return result
HEX() Hexadecimal representation of decimal or string value
Insert substring at speciUed position up to speciUed number of
INSERT()
characters
INSTR() Return the index of the Urst occurrence of substring
LCASE() Synonym for LOWER()
LEFT() Return the leftmost number of characters as speciUed
LENGTH() Return the length of a string in bytes
LIKE Simple pattern matching
LOAD_FILE() Load the named Ule
LOCATE() Return the position of the Urst occurrence of substring
LOWER() Return the argument in lowercase
LPAD() Return the string argument, left-padded with the speciUed string
LTRIM() Remove leading spaces
Return a set of comma-separated strings that have the corresponding
MAKE_SET()
bit in bits set
MATCH Perform full-text search
MID() Return a substring starting from the speciUed position
NOT LIKE Negation of simple pattern matching
NOT REGEXP Negation of REGEXP
OCT() Return a string containing octal representation of a number

OCTET_LENGTH() Synonym for LENGTH()


ORD() Return character code for leftmost character of the argument
POSITION() Synonym for LOCATE()
QUOTE() Escape the argument for use in an SQL statement
REGEXP Whether string matches regular expression
REGEXP_INSTR() Starting index of substring matching regular expression
REGEXP_LIKE() Whether string matches regular expression
REGEXP_REPLACE() Replace substrings matching regular expression
REGEXP_SUBSTR() Return substring matching regular expression
REPEAT() Repeat a string the speciUed number of times
REPLACE() Replace occurrences of a speciUed string
REVERSE() Reverse the characters in a string
RIGHT() Return the speciUed rightmost number of characters
RLIKE Whether string matches regular expression
RPAD() Append string the speciUed number of times
RTRIM() Remove trailing spaces
SOUNDEX() Return a soundex string
SOUNDS LIKE Compare sounds
SPACE() Return a string of the speciUed number of spaces
STRCMP() Compare two strings
SUBSTR() Return the substring as speciUed
SUBSTRING() Return the substring as speciUed
Return a substring from a string before the speciUed number of
SUBSTRING_INDEX()
occurrences of the delimiter
TO_BASE64() Return the argument converted to a base-64 string
TRIM() Remove leading and trailing spaces
UCASE() Synonym for UPPER()
UNHEX() Return a string containing hex representation of a number
UPPER() Convert to uppercase
WEIGHT_STRING() Return the weight string for a string

String-valued functions return NULL if the length of the result would be greater than the value of
the max_allowed_packet system variable. See Section 5.1.1, “ConUguring the Server”.
For functions that operate on string positions, the Urst position is numbered 1.

For functions that take length arguments, noninteger arguments are rounded to the nearest integer.

ASCII(str)

Returns the numeric value of the leftmost character of the string str. Returns 0 if str is the empty string.
Returns NULL if str is NULL .ASCII() works for 8-bit characters.

mysql> SELECT ASCII('2');


-> 50
mysql> SELECT ASCII(2);
-> 50
mysql> SELECT ASCII('dx');
-> 100

See also the ORD() function.

BIN(N)

Returns a string representation of the binary value of N, where N is a longlong (BIGINT) number. This is equivalent
to CONV(N,10,2). Returns NULL if N is NULL .

mysql> SELECT BIN(12);


-> '1100'

BIT_LENGTH(str)

Returns the length of the string str in bits.

mysql> SELECT BIT_LENGTH('text');


-> 32

CHAR(N,... [USING charset_name])

CHAR() interprets each argument N as an integer and returns a string consisting of the characters given by the
code values of those integers. NULL values are skipped.

mysql> SELECT CHAR(77,121,83,81,'76');


-> 'MySQL'
mysql> SELECT CHAR(77,77.3,'77.3');
-> 'MMM'

CHAR() arguments larger than 255 are converted into multiple result bytes. For example, CHAR(256) is equivalent
to CHAR(1,0), and CHAR(256*256) is equivalent to CHAR(1,0,0):

mysql> SELECT HEX(CHAR(1,0)), HEX(CHAR(256));


+----------------+----------------+
| HEX(CHAR(1,0)) | HEX(CHAR(256)) |
+----------------+----------------+
+----------------+----------------+
| 0100 | 0100 |
+----------------+----------------+
mysql> SELECT HEX(CHAR(1,0,0)), HEX(CHAR(256*256));
+------------------+--------------------+
| HEX(CHAR(1,0,0)) | HEX(CHAR(256*256)) |
+------------------+--------------------+
| 010000 | 010000 |
+------------------+--------------------+

By default, CHAR() returns a binary string. To produce a string in a given character set, use the
optional USING clause:

mysql> SELECT CHARSET(CHAR(X'65')), CHARSET(CHAR(X'65' USING utf8));


+----------------------+---------------------------------+
| CHARSET(CHAR(X'65')) | CHARSET(CHAR(X'65' USING utf8)) |
+----------------------+---------------------------------+
| binary | utf8 |
+----------------------+---------------------------------+

If USING is given and the result string is illegal for the given character set, a warning is issued. Also, if strict SQL
mode is enabled, the result from CHAR() becomes NULL .

CHAR_LENGTH(str)

Returns the length of the string str, measured in characters. A multibyte character counts as a single character.
This means that for a string containing Uve 2-byte characters, LENGTH() returns 10 ,
whereas CHAR_LENGTH() returns 5 .

CHARACTER_LENGTH(str)

CHARACTER_LENGTH() is a synonym for CHAR_LENGTH().

CONCAT(str1,str2,...)

Returns the string that results from concatenating the arguments. May have one or more arguments. If all
arguments are nonbinary strings, the result is a nonbinary string. If the arguments include any binary strings, the
result is a binary string. A numeric argument is converted to its equivalent nonbinary string form.

CONCAT() returns NULL if any argument is NULL .

mysql> SELECT CONCAT('My', 'S', 'QL');


-> 'MySQL'
mysql> SELECT CONCAT('My', NULL, 'QL');
-> NULL
mysql> SELECT CONCAT(14.3);
-> '14.3'

For quoted strings, concatenation can be performed by placing the strings next to each other:

mysql> SELECT 'My' 'S' 'QL';


-> 'MySQL'
-> 'MySQL'

CONCAT_WS(separator,str1,str2,...)

CONCAT_WS() stands for Concatenate With Separator and is a special form of CONCAT(). The Urst argument is the
separator for the rest of the arguments. The separator is added between the strings to be concatenated. The
separator can be a string, as can the rest of the arguments. If the separator is NULL , the result is NULL .

mysql> SELECT CONCAT_WS(',','First name','Second name','Last Name');


-> 'First name,Second name,Last Name'
mysql> SELECT CONCAT_WS(',','First name',NULL,'Last Name');
-> 'First name,Last Name'

CONCAT_WS() does not skip empty strings. However, it does skip any NULL values after the separator argument.

ELT(N,str1,str2,str3,...)

ELT() returns the Nth element of the list of strings: str1 if N = 1 , str2 if N = 2 , and so on. Returns NULL if N is less
than 1 or greater than the number of arguments. ELT() is the complement of FIELD().

mysql> SELECT ELT(1, 'Aa', 'Bb', 'Cc', 'Dd');


-> 'Aa'
mysql> SELECT ELT(4, 'Aa', 'Bb', 'Cc', 'Dd');
-> 'Dd'

EXPORT_SET(bits,on,off[,separator[,number_of_bits]])

Returns a string such that for every bit set in the value bits, you get an on string and for every bit not set in the
value, you get an off string. Bits in bits are examined from right to left (from low-order to high-order bits). Strings
are added to the result from left to right, separated by the separator string (the default being the comma
character , ). The number of bits examined is given by number_of_bits, which has a default of 64 if not
speciUed. number_of_bits is silently clipped to 64 if larger than 64. It is treated as an unsigned integer, so a value
of −1 is effectively the same as 64.

mysql> SELECT EXPORT_SET(5,'Y','N',',',4);


-> 'Y,N,Y,N'
mysql> SELECT EXPORT_SET(6,'1','0',',',10);
-> '0,1,1,0,0,0,0,0,0,0'

FIELD(str,str1,str2,str3,...)

Returns the index (position) of str in the str1, str2, str3, ... list. Returns 0 if str is not found.

If all arguments to FIELD() are strings, all arguments are compared as strings. If all arguments are numbers, they
are compared as numbers. Otherwise, the arguments are compared as double.

If str is NULL , the return value is 0 because NULL fails equality comparison with any value. FIELD() is the
complement of ELT().
mysql> SELECT FIELD('Bb', 'Aa', 'Bb', 'Cc', 'Dd', 'Ff');
-> 2
mysql> SELECT FIELD('Gg', 'Aa', 'Bb', 'Cc', 'Dd', 'Ff');
-> 0

FIND_IN_SET(str,strlist)

Returns a value in the range of 1 to N if the string str is in the string list strlist consisting of N substrings. A string
list is a string composed of substrings separated by , characters. If the Urst argument is a constant string and the
second is a column of type SET, the FIND_IN_SET()function is optimized to use bit arithmetic. Returns 0 if str is
not in strlist or if strlist is the empty string. Returns NULL if either argument is NULL . This function does not
work properly if the Urst argument contains a comma ( , ) character.

mysql> SELECT FIND_IN_SET('b','a,b,c,d');


-> 2

FORMAT(X,D[,locale])

Formats the number X to a format like '#,###,###.##' , rounded to D decimal places, and returns the result as a
string. If D is 0 , the result has no decimal point or fractional part.

The optional third parameter enables a locale to be speciUed to be used for the result number's decimal point,
thousands separator, and grouping between separators. Permissible locale values are the same as the legal
values for the lc_time_names system variable (see Section 10.15, “MySQL Server Locale Support”). If no locale is
speciUed, the default is 'en_US' .

mysql> SELECT FORMAT(12332.123456, 4);


-> '12,332.1235'
mysql> SELECT FORMAT(12332.1,4);
-> '12,332.1000'
mysql> SELECT FORMAT(12332.2,0);
-> '12,332'
mysql> SELECT FORMAT(12332.2,2,'de_DE');
-> '12.332,20'

FROM_BASE64(str)

Takes a string encoded with the base-64 encoded rules used by TO_BASE64() and returns the decoded result as a
binary string. The result is NULL if the argument is NULL or not a valid base-64 string. See the description
of TO_BASE64() for details about the encoding and decoding rules.

mysql> SELECT TO_BASE64('abc'), FROM_BASE64(TO_BASE64('abc'));


-> 'JWJj', 'abc'

HEX(str), HEX(N)

For a string argument str, HEX() returns a hexadecimal string representation of str where each byte of each
character in str is converted to two hexadecimal digits. (Multibyte characters therefore become more than two
character in str is converted to two hexadecimal digits. (Multibyte characters therefore become more than two
digits.) The inverse of this operation is performed by theUNHEX() function.

For a numeric argument N, HEX() returns a hexadecimal string representation of the value of N treated as a
longlong (BIGINT) number. This is equivalent to CONV(N,10,16). The inverse of this operation is performed
by CONV(HEX(N),16,10).

mysql> SELECT X'616263', HEX('abc'), UNHEX(HEX('abc'));


-> 'abc', 616263, 'abc'
mysql> SELECT HEX(255), CONV(HEX(255),16,10);
-> 'FF', 255

INSERT(str,pos,len,newstr)

Returns the string str, with the substring beginning at position pos and len characters long replaced by the
string newstr. Returns the original string if pos is not within the length of the string. Replaces the rest of the string
from position pos if len is not within the length of the rest of the string. Returns NULL if any argument is NULL .

mysql> SELECT INSERT('Quadratic', 3, 4, 'What');


-> 'QuWhattic'
mysql> SELECT INSERT('Quadratic', -1, 4, 'What');
-> 'Quadratic'
mysql> SELECT INSERT('Quadratic', 3, 100, 'What');
-> 'QuWhat'

This function is multibyte safe.

INSTR(str,substr)

Returns the position of the Urst occurrence of substring substr in string str. This is the same as the two-argument
form of LOCATE(), except that the order of the arguments is reversed.

mysql> SELECT INSTR('foobarbar', 'bar');


-> 4
mysql> SELECT INSTR('xbar', 'foobar');
-> 0

This function is multibyte safe, and is case-sensitive only if at least one argument is a binary string.

LCASE(str)

LCASE() is a synonym for LOWER().

LCASE() used in a view is rewritten as LOWER() when storing the view's deUnition. (Bug #12844279)

LEFT(str,len)

Returns the leftmost len characters from the string str, or NULL if any argument is NULL .
mysql> SELECT LEFT('foobarbar', 5);
-> 'fooba'

This function is multibyte safe.

LENGTH(str)

Returns the length of the string str, measured in bytes. A multibyte character counts as multiple bytes. This
means that for a string containing Uve 2-byte characters, LENGTH() returns 10 , whereas CHAR_LENGTH() returns 5 .

mysql> SELECT LENGTH('text');


-> 4

Note
The Length() OpenGIS spatial function is named ST_Length() in MySQL.

LOAD_FILE(file_name)

Reads the Ule and returns the Ule contents as a string. To use this function, the Ule must be located on the server
host, you must specify the full path name to the Ule, and you must have the FILE privilege. The Ule must be
readable by the server and its size less thanmax_allowed_packet bytes. If the secure_file_priv system variable is
set to a nonempty directory name, the Ule to be loaded must be located in that directory. (Prior to MySQL 8.0.17,
the Ule must be readable by all, not just readable by the server.)

If the Ule does not exist or cannot be read because one of the preceding conditions is not satisUed, the function
returns NULL .

The character_set_filesystem system variable controls interpretation of Ule names that are given as literal
strings.

mysql> UPDATE t
SET blob_col=LOAD_FILE('/tmp/picture')
WHERE id=1;

LOCATE(substr,str), LOCATE(substr,str,pos)

The Urst syntax returns the position of the Urst occurrence of substring substr in string str. The second syntax
returns the position of the Urst occurrence of substring substr in string str, starting at position pos.
Returns 0 if substr is not in str. Returns NULL if any argument is NULL .

mysql> SELECT LOCATE('bar', 'foobarbar');


-> 4
mysql> SELECT LOCATE('xbar', 'foobar');
-> 0
mysql> SELECT LOCATE('bar', 'foobarbar', 5);
-> 7

This function is multibyte safe, and is case-sensitive only if at least one argument is a binary string.

LOWER(str)
Returns the string str with all characters changed to lowercase according to the current character set mapping.
The default is utf8mb4 .

mysql> SELECT LOWER('QUADRATICALLY');


-> 'quadratically'

LOWER() (and UPPER()) are ineffective when applied to binary strings (BINARY, VARBINARY, BLOB). To perform
lettercase conversion, convert the string to a nonbinary string:

mysql> SET @str = BINARY 'New York';


mysql> SELECT LOWER(@str), LOWER(CONVERT(@str USING utf8mb4));
+-------------+------------------------------------+
| LOWER(@str) | LOWER(CONVERT(@str USING utf8mb4)) |
+-------------+------------------------------------+
| New York | new york |
+-------------+------------------------------------+

For collations of Unicode character sets, LOWER() and UPPER() work according to the Unicode Collation Algorithm
(UCA) version in the collation name, if there is one, and UCA 4.0.0 if no version is speciUed. For
example, utf8mb4_0900_ai_ci and utf8_unicode_520_ci work according to UCA 9.0.0 and 5.2.0, respectively,
whereas utf8_unicode_ci works according to UCA 4.0.0. See Section 10.10.1, “Unicode Character Sets”.

This function is multibyte safe.

LCASE() used within views is rewritten as LOWER() .

LPAD(str,len,padstr)

Returns the string str, left-padded with the string padstr to a length of len characters. If str is longer than len, the
return value is shortened to len characters.

mysql> SELECT LPAD('hi',4,'??');


-> '??hi'
mysql> SELECT LPAD('hi',1,'??');
-> 'h'

LTRIM(str)

Returns the string str with leading space characters removed.

mysql> SELECT LTRIM(' barbar');


-> 'barbar'

This function is multibyte safe.

MAKE_SET(bits,str1,str2,...)

Returns a set value (a string containing substrings separated by , characters) consisting of the strings that have
the corresponding bit in bitsset. str1 corresponds to bit 0, str2 to bit 1, and so on. NULL values
in str1, str2, ... are not appended to the result.
mysql> SELECT MAKE_SET(1,'a','b','c');
-> 'a'
mysql> SELECT MAKE_SET(1 | 4,'hello','nice','world');
-> 'hello,world'
mysql> SELECT MAKE_SET(1 | 4,'hello','nice',NULL,'world');
-> 'hello'
mysql> SELECT MAKE_SET(0,'a','b','c');
-> ''

MID(str,pos,len)

MID(str,pos,len) is a synonym for SUBSTRING(str,pos,len).

OCT(N)

Returns a string representation of the octal value of N, where N is a longlong (BIGINT) number. This is equivalent
to CONV(N,10,8). Returns NULL if N is NULL .

mysql> SELECT OCT(12);


-> '14'

OCTET_LENGTH(str)

OCTET_LENGTH() is a synonym for LENGTH().

ORD(str)

If the leftmost character of the string str is a multibyte character, returns the code for that character, calculated
from the numeric values of its constituent bytes using this formula:

(1st byte code)


+ (2nd byte code * 256)
+ (3rd byte code * 256^2) ...

If the leftmost character is not a multibyte character, ORD() returns the same value as the ASCII() function.

mysql> SELECT ORD('2');


-> 50

POSITION(substr IN str)

POSITION(substr IN str) is a synonym for LOCATE(substr,str).

QUOTE(str)

Quotes a string to produce a result that can be used as a properly escaped data value in an SQL statement. The
string is returned enclosed by single quotation marks and with each instance of backslash ( \ ), single quote ( ' ),
ASCII NUL , and Control+Z preceded by a backslash. If the argument is NULL , the return value is the
word “NULL” without enclosing single quotation marks.

mysql> SELECT QUOTE('Don\'t!');


-> 'Don\'t!'
mysql> SELECT QUOTE(NULL);
-> NULL

For comparison, see the quoting rules for literal strings and within the C API in Section 9.1.1, “String Literals”,
and Section 28.7.7.56, “mysql_real_escape_string_quote()”.

REPEAT(str,count)

Returns a string consisting of the string str repeated count times. If count is less than 1, returns an empty string.
Returns NULL if str orcount are NULL .

mysql> SELECT REPEAT('MySQL', 3);


-> 'MySQLMySQLMySQL'

REPLACE(str,from_str,to_str)

Returns the string str with all occurrences of the string from_str replaced by the
string to_str. REPLACE() performs a case-sensitive match when searching for from_str.

mysql> SELECT REPLACE('www.mysql.com', 'w', 'Ww');


-> 'WwWwWw.mysql.com'

This function is multibyte safe.

REVERSE(str)

Returns the string str with the order of the characters reversed.

mysql> SELECT REVERSE('abc');


-> 'cba'

This function is multibyte safe.

RIGHT(str,len)

Returns the rightmost len characters from the string str, or NULL if any argument is NULL .

mysql> SELECT RIGHT('foobarbar', 4);


-> 'rbar'

This function is multibyte safe.

RPAD(str,len,padstr)

Returns the string str, right-padded with the string padstr to a length of len characters. If str is longer than len,
the return value is shortened to len characters.

mysql> SELECT RPAD('hi',5,'?');


-> 'hi???'
mysql> SELECT RPAD('hi',1,'?');
mysql> SELECT RPAD('hi',1,'?');
-> 'h'

This function is multibyte safe.

RTRIM(str)

Returns the string str with trailing space characters removed.

mysql> SELECT RTRIM('barbar ');


-> 'barbar'

This function is multibyte safe.

SOUNDEX(str)

Returns a soundex string from str. Two strings that sound almost the same should have identical soundex
strings. A standard soundex string is four characters long, but the SOUNDEX() function returns an arbitrarily long
string. You can use SUBSTRING() on the result to get a standard soundex string. All nonalphabetic characters
in str are ignored. All international alphabetic characters outside the A-Z range are treated as vowels.

Important
When using SOUNDEX(), you should be aware of the following limitations:

This function, as currently implemented, is intended to work well with strings that are in the English language
only. Strings in other languages may not produce reliable results.

This function is not guaranteed to provide consistent results with strings that use multibyte character sets,
including utf-8 . See Bug #22638 for more information.

mysql> SELECT SOUNDEX('Hello');


-> 'H400'
mysql> SELECT SOUNDEX('Quadratically');
-> 'Q36324'

Note
This function implements the original Soundex algorithm, not the more popular enhanced version (also described
by D. Knuth). The difference is that original version discards vowels Urst and duplicates second, whereas the
enhanced version discards duplicates Urst and vowels second.

expr1 SOUNDS LIKE expr2

This is the same as SOUNDEX(expr1) = SOUNDEX(expr2).

SPACE(N)

Returns a string consisting of N space characters.

mysql> SELECT SPACE(6);


-> ' '
SUBSTR(str,pos), SUBSTR(str FROM pos), SUBSTR(str,pos,len), SUBSTR(str FROM pos FOR len)

SUBSTR() is a synonym for SUBSTRING().

SUBSTRING(str,pos), SUBSTRING(str FROM pos), SUBSTRING(str,pos,len), SUBSTRING(str FROM pos FOR len)

The forms without a len argument return a substring from string str starting at position pos. The forms with
a len argument return a substring len characters long from string str, starting at position pos. The forms that
use FROM are standard SQL syntax. It is also possible to use a negative value for pos. In this case, the beginning of

the substring is pos characters from the end of the string, rather than the beginning. A negative value may be used
for pos in any of the forms of this function.

For all forms of SUBSTRING(), the position of the Urst character in the string from which the substring is to be
extracted is reckoned as 1 .

mysql> SELECT SUBSTRING('Quadratically',5);


-> 'ratically'
mysql> SELECT SUBSTRING('foobarbar' FROM 4);
-> 'barbar'
mysql> SELECT SUBSTRING('Quadratically',5,6);
-> 'ratica'
mysql> SELECT SUBSTRING('Sakila', -3);
-> 'ila'
mysql> SELECT SUBSTRING('Sakila', -5, 3);
-> 'aki'
mysql> SELECT SUBSTRING('Sakila' FROM -4 FOR 2);
-> 'ki'

This function is multibyte safe.

If len is less than 1, the result is the empty string.

SUBSTRING_INDEX(str,delim,count)

Returns the substring from string str before count occurrences of the delimiter delim. If count is positive,
everything to the left of the Unal delimiter (counting from the left) is returned. If count is negative, everything to the
right of the Unal delimiter (counting from the right) is returned. SUBSTRING_INDEX() performs a case-sensitive
match when searching for delim.

mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', 2);


-> 'www.mysql'
mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', -2);
-> 'mysql.com'

This function is multibyte safe.

TO_BASE64(str)

Converts the string argument to base-64 encoded form and returns the result as a character string with the
connection character set and collation. If the argument is not a string, it is converted to a string before conversion
takes place. The result is NULL if the argument is NULL . Base-64 encoded strings can be decoded using
takes place. The result is NULL if the argument is NULL . Base-64 encoded strings can be decoded using
the FROM_BASE64() function.

mysql> SELECT TO_BASE64('abc'), FROM_BASE64(TO_BASE64('abc'));


-> 'JWJj', 'abc'

Different base-64 encoding schemes exist. These are the encoding and decoding rules used
by TO_BASE64() and FROM_BASE64():

The encoding for alphabet value 62 is '+' .

The encoding for alphabet value 63 is '/' .

Encoded output consists of groups of 4 printable characters. Each 3 bytes of the input data are encoded using
4 characters. If the last group is incomplete, it is padded with '=' characters to a length of 4.

A newline is added after each 76 characters of encoded output to divide long output into multiple lines.

Decoding recognizes and ignores newline, carriage return, tab, and space.

TRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str), TRIM([remstr FROM] str)

Returns the string str with all remstr preUxes or supxes removed. If none of the speciUers BOTH , LEADING ,
or TRAILING is given, BOTH is assumed. remstr is optional and, if not speciUed, spaces are removed.

mysql> SELECT TRIM(' bar ');


-> 'bar'
mysql> SELECT TRIM(LEADING 'x' FROM 'xxxbarxxx');
-> 'barxxx'
mysql> SELECT TRIM(BOTH 'x' FROM 'xxxbarxxx');
-> 'bar'
mysql> SELECT TRIM(TRAILING 'xyz' FROM 'barxxyz');
-> 'barx'

This function is multibyte safe.

UCASE(str)

UCASE() is a synonym for UPPER().

UCASE() used within views is rewritten as UPPER() .

UNHEX(str)

For a string argument str, UNHEX(str) interprets each pair of characters in the argument as a hexadecimal number
and converts it to the byte represented by the number. The return value is a binary string.

mysql> SELECT UNHEX('4D7953514C');


-> 'MySQL'
mysql> SELECT X'4D7953514C';
-> 'MySQL'
mysql> SELECT UNHEX(HEX('string'));
-> 'string'
mysql> SELECT HEX(UNHEX('1267'));
mysql> SELECT HEX(UNHEX('1267'));
-> '1267'

The characters in the argument string must be legal hexadecimal digits: '0' .. '9' , 'A' .. 'F' , 'a' .. 'f' . If the
argument contains any nonhexadecimal digits, the result is NULL :

mysql> SELECT UNHEX('GG');


+-------------+
| UNHEX('GG') |
+-------------+
| NULL |
+-------------+

A NULL result can occur if the argument to UNHEX() is a BINARY column, because values are padded with 0x00
bytes when stored but those bytes are not stripped on retrieval. For example, '41' is stored into
a CHAR(3) column as '41 ' and retrieved as '41' (with the trailing pad space stripped), so UNHEX() for the
column value returns 'A' . By contrast '41' is stored into a BINARY(3) column as '41\0' and retrieved
as '41\0' (with the trailing pad 0x00 byte not stripped). '\0' is not a legal hexadecimal digit, so UNHEX() for the
column value returns NULL .

For a numeric argument N, the inverse of HEX(N) is not performed by UNHEX(). Use CONV(HEX(N),16,10) instead.
See the description ofHEX().

UPPER(str)

Returns the string str with all characters changed to uppercase according to the current character set mapping.
The default is utf8mb4 .

mysql> SELECT UPPER('Hej');


-> 'HEJ'

See the description of LOWER() for information that also applies to UPPER(). This included information about how
to perform lettercase conversion of binary strings (BINARY, VARBINARY, BLOB) for which these functions are
ineffective, and information about case folding for Unicode character sets.

This function is multibyte safe.

UCASE() used within views is rewritten as UPPER() .

WEIGHT_STRING(str [AS {CHAR|BINARY}(N)] [flags])

This function returns the weight string for the input string. The return value is a binary string that represents the
comparison and sorting value of the string. It has these properties:

If WEIGHT_STRING(str1) = WEIGHT_STRING(str2), then str1 = str2 (str1 and str2 are considered equal)

If WEIGHT_STRING(str1) < WEIGHT_STRING(str2), then str1 < str2 (str1 sorts before str2)
WEIGHT_STRING() is a debugging function intended for internal use. Its behavior can change without notice
between MySQL versions. It can be used for testing and debugging of collations, especially if you are adding a new
collation. See Section 10.13, “Adding a Collation to a Character Set”.

This list briery summarizes the arguments. More details are given in the discussion following the list.

str: The input string expression.

AS clause: Optional; cast the input string to a given type and length.

flags: Optional; unused.

The input string, str, is a string expression. If the input is a nonbinary (character) string such as a CHAR, VARCHAR,
or TEXT value, the return value contains the collation weights for the string. If the input is a binary (byte) string such
as a BINARY, VARBINARY, or BLOB value, the return value is the same as the input (the weight for each byte in a binary
string is the byte value). If the input is NULL , WEIGHT_STRING() returns NULL .

Examples:

mysql> SET @s = _utf8mb4 'AB' COLLATE utf8mb4_0900_ai_ci;


mysql> SELECT @s, HEX(@s), HEX(WEIGHT_STRING(@s));
+------+---------+------------------------+
| @s | HEX(@s) | HEX(WEIGHT_STRING(@s)) |
+------+---------+------------------------+
| AB | 4142 | 1C471C60 |
+------+---------+------------------------+

mysql> SET @s = _utf8mb4 'ab' COLLATE utf8mb4_0900_ai_ci;


mysql> SELECT @s, HEX(@s), HEX(WEIGHT_STRING(@s));
+------+---------+------------------------+
| @s | HEX(@s) | HEX(WEIGHT_STRING(@s)) |
+------+---------+------------------------+
| ab | 6162 | 1C471C60 |
+------+---------+------------------------+

mysql> SET @s = CAST('AB' AS BINARY);


mysql> SELECT @s, HEX(@s), HEX(WEIGHT_STRING(@s));
+------+---------+------------------------+
| @s | HEX(@s) | HEX(WEIGHT_STRING(@s)) |
+------+---------+------------------------+
| AB | 4142 | 4142 |
+------+---------+------------------------+

mysql> SET @s = CAST('ab' AS BINARY);


mysql> SELECT @s, HEX(@s), HEX(WEIGHT_STRING(@s));
+------+---------+------------------------+
| @s | HEX(@s) | HEX(WEIGHT_STRING(@s)) |
+------+---------+------------------------+
| ab | 6162 | 6162 |
+------+---------+------------------------+
+------+---------+------------------------+

The preceding examples use HEX() to display the WEIGHT_STRING() result. Because the result is a binary
value, HEX() can be especially useful when the result contains nonprinting values, to display it in printable form:

mysql> SET @s = CONVERT(X'C39F' USING utf8) COLLATE utf8_czech_ci;


mysql> SELECT HEX(WEIGHT_STRING(@s));
+------------------------+
| HEX(WEIGHT_STRING(@s)) |
+------------------------+
| 0FEA0FEA |
+------------------------+

For non- NULL return values, the data type of the value is VARBINARY if its length is within the maximum length
for VARBINARY, otherwise the data type is BLOB.

The AS clause may be given to cast the input string to a nonbinary or binary string and to force it to a given length:

AS CHAR(N) casts the string to a nonbinary string and pads it on the right with spaces to a length
of N characters. N must be at least 1. IfN is less than the length of the input string, the string is truncated
to N characters. No warning occurs for truncation.

AS BINARY(N) is similar but casts the string to a binary string, N is measured in bytes (not characters), and
padding uses 0x00 bytes (not spaces).

mysql> SET NAMES 'latin1';


mysql> SELECT HEX(WEIGHT_STRING('ab' AS CHAR(4)));
+-------------------------------------+
| HEX(WEIGHT_STRING('ab' AS CHAR(4))) |
+-------------------------------------+
| 41422020 |
+-------------------------------------+
mysql> SET NAMES 'utf8';
mysql> SELECT HEX(WEIGHT_STRING('ab' AS CHAR(4)));
+-------------------------------------+
| HEX(WEIGHT_STRING('ab' AS CHAR(4))) |
+-------------------------------------+
| 0041004200200020 "Success occurs
| when opportunity meets preparation."
+-------------------------------------+
      

You are logged


mysql> SELECT HEX(WEIGHT_STRING('ab' in as Andrew Francisco (Log out)
AS BINARY(4)));
+---------------------------------------+
| HEX(WEIGHT_STRING('ab' AS BINARY(4))) |
+---------------------------------------+
+---------------------------------------+
| 61620000 | © CodingNomads 2022
Copyright

+---------------------------------------+

◀︎ Control Flow Functions Reference Numeric Functions & Operators Reference ▶︎


          Andrew Francisco

Dashboard Course Options Members-Only Forum About

 Dashboard / My courses / SQL & Databases / Sections / 7) Extended MySQL Functions Reference
/ Numeric Functions & Operators Reference

Numeric Functions & Operators Reference

Sourced from MySQL Docs here: https://dev.mysql.com/doc/refman/8.0/en/numeric-functions.html

Name Description
ABS() Return the absolute value
ACOS() Return the arc cosine
ASIN() Return the arc sine
ATAN() Return the arc tangent
ATAN2(), ATAN() Return the arc tangent of the two arguments
CEIL() Return the smallest integer value not less than the argument
CEILING() Return the smallest integer value not less than the argument
CONV() Convert numbers between different number bases
COS() Return the cosine
COT() Return the cotangent
CRC32() Compute a cyclic redundancy check value
DEGREES() Convert radians to degrees
DIV Integer division
/ Division operator
EXP() Raise to the power of
FLOOR() Return the largest integer value not greater than the argument
LN() Return the natural logarithm of the argument
LOG() Return the natural logarithm of the Qrst argument
LOG10() Return the base-10 logarithm of the argument
LOG2() Return the base-2 logarithm of the argument
- Minus operator
MOD() Return the remainder
%, MOD Modulo operator
PI() Return the value of pi
+ Addition operator
POW() Return the argument raised to the speciQed power
POWER() Return the argument raised to the speciQed power
RADIANS() Return argument converted to radians
RAND() Return a random Yoating-point value
ROUND() Round the argument
SIGN() Return the sign of the argument
SIN() Return the sine of the argument
SQRT() Return the square root of the argument
TAN() Return the tangent of the argument
* Multiplication operator
TRUNCATE() Truncate to speciQed number of decimal places
- Change the sign of the argument

◀︎ String Functions Reference Arithmetic Operators Reference ▶︎

"Success occurs when opportunity meets preparation."

      

You are logged in as Andrew Francisco (Log out)

Copyright © CodingNomads 2022


Arithmetic Operators Reference
Sourced from MySQL Docs
here: https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html
Name Description
DIV Integer division
/ Division operator
- Minus operator
%, MOD Modulo operator
+ Addition operator
* Multiplication operator
- Change the sign of the argument

The usual arithmetic operators are available. The result is determined


according to the following rules:

In the case of -, +, and *, the result is calculated with BIGINT (64-bit)


precision if both operands are integers.

If both operands are integers and any of them are unsigned, the result is
an unsigned integer. For subtraction, if
theNO_UNSIGNED_SUBTRACTION SQL mode is enabled, the result is signed
even if any operand is unsigned.

If any of the operands of a +, -, /, *, % is a real or string value, the


precision of the result is the precision of the operand with the maximum
precision.

In division performed with /, the scale of the result when using two
exact-value operands is the scale of the first operand plus the value of
thediv_precision_increment system variable (which is 4 by default).
For example, the result of the expression 5.05 / 0.014 has a scale of
six decimal places (360.714286).

These rules are applied for each operation, such that nested calculations
imply the precision of each component. Hence, (14620 / 9432456) /
(24250 / 9432456), resolves first to (0.0014) / (0.0026), with the final
result having 8 decimal places (0.60288653).

Because of these rules and the way they are applied, care should be taken to
ensure that components and subcomponents of a calculation use the
appropriate level of precision. See Section 12.10, “Cast Functions and
Operators”.

For information about handling of overflow in numeric expression evaluation,


see Section 11.2.6, “Out-of-Range and Overflow Handling”.

Arithmetic operators apply to numbers. For other types of values, alternative


operations may be available. For example, to add date values,
use DATE_ADD(); see Section 12.7, “Date and Time Functions”.

Addition:

mysql> SELECT 3+5;


-> 8

Subtraction:

mysql> SELECT 3-5;


-> -2
-

Unary minus. This operator changes the sign of the operand.

mysql> SELECT - 2;
-> -2

Note

If this operator is used with a BIGINT, the return value is also a BIGINT.
This means that you should avoid using - on integers that may have the
value of −263.

Multiplication:

mysql> SELECT 3*5;


-> 15
mysql> SELECT 18014398509481984*18014398509481984.0;
-> 324518553658426726783156020576256.0
mysql> SELECT 18014398509481984*18014398509481984;
-> out-of-range error

The last expression produces an error because the result of the integer
multiplication exceeds the 64-bit range of BIGINT calculations.
(SeeSection 11.2, “Numeric Types”.)

Division:
mysql> SELECT 3/5;
-> 0.60

Division by zero produces a NULL result:

mysql> SELECT 102/(1-1);


-> NULL

A division is calculated with BIGINT arithmetic only if performed in a


context where its result is converted to an integer.

DIV

Integer division. Discards from the division result any fractional part to
the right of the decimal point.

If either operand has a noninteger type, the operands are converted


to DECIMAL and divided using DECIMAL arithmetic before converting the
result to BIGINT. If the result exceeds BIGINT range, an error occurs.

mysql> SELECT 5 DIV 2, -5 DIV 2, 5 DIV -2, -5 DIV -2;


-> 2, -2, -2, 2

N % M, N MOD M

Modulo operation. Returns the remainder of N divided by M.


 Dashboard / My courses / SQL & Databases / Sections / 7) Extended MySQL Functions Reference
/ Aggregate (GROUP BY) Functions Reference

Aggregate (GROUP BY) Functions Reference

Sourced from MySQL Docs here: https://dev.mysql.com/doc/refman/8.0/en/group-by-functions.html

Name Description
AVG() Return the average value of the argument
BIT_AND() Return bitwise AND
BIT_OR() Return bitwise OR
BIT_XOR() Return bitwise XOR
COUNT() Return a count of the number of rows returned
COUNT(DISTINCT) Return the count of a number of different values
GROUP_CONCAT() Return a concatenated string
JSON_ARRAYAGG() Return result set as a single JSON array
JSON_OBJECTAGG() Return result set as a single JSON object
MAX() Return the maximum value
MIN() Return the minimum value
STD() Return the population standard deviation
STDDEV() Return the population standard deviation
STDDEV_POP() Return the population standard deviation
STDDEV_SAMP() Return the sample standard deviation
SUM() Return the sum
VAR_POP() Return the population standard variance
VAR_SAMP() Return the sample variance
VARIANCE() Return the population standard variance

Unless otherwise stated, group functions ignore NULL values.

If you use a group function in a statement containing no GROUP BY clause, it is equivalent to grouping on all rows. For
more information, seeSection 12.20.3, “MySQL Handling of GROUP BY”.

Most aggregate functions can be used as window functions. Those that can be used this way are signi`ed in their
syntax description by [over_clause] , representing an optional OVER clause. over_clause is described in Section 12.21.2,
“Window Function Concepts and Syntax”, which also includes other information about window function usage.
For numeric arguments, the variance and standard deviation functions return a DOUBLE value.
The SUM() and AVG() functions return a DECIMALvalue for exact-value arguments (integer or DECIMAL), and a DOUBLE value
for approximate-value arguments (FLOAT or DOUBLE).

The SUM() and AVG() aggregate functions do not work with temporal values. (They convert the values to numbers,
losing everything after the `rst nonnumeric character.) To work around this problem, convert to numeric units, perform
the aggregate operation, and convert back to a temporal value. Examples:

SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(time_col))) FROM tbl_name;


SELECT FROM_DAYS(SUM(TO_DAYS(date_col))) FROM tbl_name;

Functions such as SUM() or AVG() that expect a numeric argument cast the argument to a number if necessary.
For SET or ENUM values, the cast operation causes the underlying numeric value to be used.

The BIT_AND(), BIT_OR(), and BIT_XOR() aggregate functions perform bit operations. Prior to MySQL 8.0, bit functions
and operators required BIGINT (64-bit integer) arguments and returned BIGINT values, so they had a maximum range of
64 bits. Non-BIGINT arguments were converted to BIGINT prior to performing the operation and truncation could occur.

In MySQL 8.0, bit functions and operators permit binary string type arguments (BINARY, VARBINARY, and the BLOB types)
and return a value of like type, which enables them to take arguments and produce return values larger than 64 bits. For
discussion about argument evaluation and result types for bit operations, see the introductory discussion
in Section 12.12, “Bit Functions and Operators”.

AVG([DISTINCT] expr) [over_clause]

Returns the average value of expr . The DISTINCT option can be used to return the average of the distinct values
of expr.

If there are no matching rows, AVG() returns NULL .

This function executes as a window function if over_clause is present. over_clause is as described


in Section 12.21.2, “Window Function Concepts and Syntax”; it cannot be used with DISTINCT .

mysql> SELECT student_name, AVG(test_score)


FROM student
GROUP BY student_name;

BIT_AND(expr) [over_clause]

Returns the bitwise AND of all bits in expr.

The result type depends on whether the function argument values are evaluated as binary strings or numbers:

Binary-string evaluation occurs when the argument values have a binary string type, and the argument is not a
hexadecimal literal, bit literal, or NULL literal. Numeric evaluation occurs otherwise, with argument value
conversion to unsigned 64-bit integers as necessary.

Binary-string evaluation produces a binary string of the same length as the argument values. If argument values
have unequal lengths, anER_INVALID_BITWISE_OPERANDS_SIZE error occurs. If the argument size exceeds 511
bytes, anER_INVALID_BITWISE_AGGREGATE_OPERANDS_SIZE error occurs. Numeric evaluation produces an unsigned
64-bit integer.
If there are no matching rows, BIT_AND() returns a neutral value (all bits set to 1) having the same length as the
argument values.

NULL values do not affect the result unless all values are NULL . In that case, the result is a neutral value having the
same length as the argument values.

For more information discussion about argument evaluation and result types, see the introductory discussion
in Section 12.12, “Bit Functions and Operators”.

As of MySQL 8.0.12, this function executes as a window function if over_clause is present. over_clause is as
described in Section 12.21.2, “Window Function Concepts and Syntax”.

BIT_OR(expr) [over_clause]

Returns the bitwise OR of all bits in expr.

The result type depends on whether the function argument values are evaluated as binary strings or numbers:

Binary-string evaluation occurs when the argument values have a binary string type, and the argument is not a
hexadecimal literal, bit literal, or NULL literal. Numeric evaluation occurs otherwise, with argument value
conversion to unsigned 64-bit integers as necessary.

Binary-string evaluation produces a binary string of the same length as the argument values. If argument values
have unequal lengths, anER_INVALID_BITWISE_OPERANDS_SIZE error occurs. If the argument size exceeds 511
bytes, anER_INVALID_BITWISE_AGGREGATE_OPERANDS_SIZE error occurs. Numeric evaluation produces an unsigned
64-bit integer.

If there are no matching rows, BIT_OR() returns a neutral value (all bits set to 0) having the same length as the
argument values.

NULL values do not affect the result unless all values are NULL . In that case, the result is a neutral value having the
same length as the argument values.

For more information discussion about argument evaluation and result types, see the introductory discussion
in Section 12.12, “Bit Functions and Operators”.

As of MySQL 8.0.12, this function executes as a window function if over_clause is present. over_clause is as
described in Section 12.21.2, “Window Function Concepts and Syntax”.

BIT_XOR(expr) [over_clause]

Returns the bitwise XOR of all bits in expr.

The result type depends on whether the function argument values are evaluated as binary strings or numbers:

Binary-string evaluation occurs when the argument values have a binary string type, and the argument is not a
hexadecimal literal, bit literal, or NULL literal. Numeric evaluation occurs otherwise, with argument value
conversion to unsigned 64-bit integers as necessary.

Binary-string evaluation produces a binary string of the same length as the argument values. If argument values
have unequal lengths, anER_INVALID_BITWISE_OPERANDS_SIZE error occurs. If the argument size exceeds 511
bytes, anER_INVALID_BITWISE_AGGREGATE_OPERANDS_SIZE error occurs. Numeric evaluation produces an unsigned
64-bit integer.
If there are no matching rows, BIT_XOR() returns a neutral value (all bits set to 0) having the same length as the
argument values.

NULL values do not affect the result unless all values are NULL . In that case, the result is a neutral value having the
same length as the argument values.

For more information discussion about argument evaluation and result types, see the introductory discussion
in Section 12.12, “Bit Functions and Operators”.

As of MySQL 8.0.12, this function executes as a window function if over_clause is present. over_clause is as
described in Section 12.21.2, “Window Function Concepts and Syntax”.

COUNT(expr) [over_clause]

Returns a count of the number of non- NULL values of expr in the rows retrieved by a SELECT statement. The result is
a BIGINT value.

If there are no matching rows, COUNT() returns 0 .

This function executes as a window function if over_clause is present. over_clause is as described


in Section 12.21.2, “Window Function Concepts and Syntax”.

mysql> SELECT student.student_name,COUNT(*)


FROM student,course
WHERE student.student_id=course.student_id
GROUP BY student_name;

COUNT(*) is somewhat different in that it returns a count of the number of rows retrieved, whether or not they
contain NULL values.

For transactional storage engines such as InnoDB , storing an exact row count is problematic. Multiple transactions
may be occurring at the same time, each of which may affect the count.

InnoDB does not keep an internal count of rows in a table because concurrent transactions might “see” different
numbers of rows at the same time. Consequently, SELECT COUNT(*) statements only count rows visible to the
current transaction.

As of MySQL 8.0.13, SELECT COUNT(*) FROM tbl_name query performance for InnoDB tables is optimized for single-
threaded workloads if there are no extra clauses such as WHERE or GROUP BY .

InnoDB processes SELECT COUNT(*) statements by traversing the smallest available secondary index unless an
index or optimizer hint directs the optimizer to use a different index. If a secondary index is not
present, InnoDB processes SELECT COUNT(*) statements by scanning the clustered index.

Processing SELECT COUNT(*) statements takes some time if index records are not entirely in the buffer pool. For a
faster count, create a counter table and let your application update it according to the inserts and deletes it does.
However, this method may not scale well in situations where thousands of concurrent transactions are initiating
updates to the same counter table. If an approximate row count is suicient, use SHOW TABLE STATUS.

InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance
difference.
For MyISAM tables, COUNT(*) is optimized to return very quickly if the SELECT retrieves from one table, no other
columns are retrieved, and there is no WHERE clause. For example:

mysql> SELECT COUNT(*) FROM student;

This optimization only applies to MyISAM tables, because an exact row count is stored for this storage engine and
can be accessed very quickly. COUNT(1) is only subject to the same optimization if the `rst column is de`ned as NOT
NULL .

COUNT(DISTINCT expr,[expr...])

Returns a count of the number of rows with different non- NULL expr values.

If there are no matching rows, COUNT(DISTINCT) returns 0 .

mysql> SELECT COUNT(DISTINCT results) FROM student;

In MySQL, you can obtain the number of distinct expression combinations that do not contain NULL by giving a list
of expressions. In standard SQL, you would have to do a concatenation of all expressions inside COUNT(DISTINCT
...).

GROUP_CONCAT(expr)

This function returns a string result with the concatenated non- NULL values from a group. It returns NULL if there
are no non- NULL values. The full syntax is as follows:

GROUP_CONCAT([DISTINCT] expr [,expr ...]


[ORDER BY {unsigned_integer | col_name | expr}
[ASC | DESC] [,col_name ...]]
[SEPARATOR str_val])

mysql> SELECT student_name,


GROUP_CONCAT(test_score)
FROM student
GROUP BY student_name;

Or:

mysql> SELECT student_name,


GROUP_CONCAT(DISTINCT test_score
ORDER BY test_score DESC SEPARATOR ' ')
FROM student
GROUP BY student_name;

In MySQL, you can get the concatenated values of expression combinations. To eliminate duplicate values, use
the DISTINCT clause. To sort values in the result, use the ORDER BY clause. To sort in reverse order, add
the DESC (descending) keyword to the name of the column you are sorting by in the ORDER BY clause. The default is
ascending order; this may be speci`ed explicitly using the ASC keyword. The default separator between values in a
group is comma ( , ). To specify a separator explicitly, use SEPARATOR followed by the string literal value that should
be inserted between group values. To eliminate the separator altogether, specify SEPARATOR '' .
The result is truncated to the maximum length that is given by the group_concat_max_len system variable, which has
a default value of 1024. The value can be set higher, although the effective maximum length of the return value is
constrained by the value of max_allowed_packet. The syntax to change the value of group_concat_max_len at
runtime is as follows, where val is an unsigned integer:

SET [GLOBAL | SESSION] group_concat_max_len = val;

The return value is a nonbinary or binary string, depending on whether the arguments are nonbinary or binary
strings. The result type is TEXTor BLOB unless group_concat_max_len is less than or equal to 512, in which case the
result type is VARCHAR or VARBINARY.

See also CONCAT() and CONCAT_WS(): Section 12.5, “String Functions”.

JSON_ARRAYAGG(col_or_expr) [over_clause]

Aggregates a result set as a single JSON array whose elements consist of the rows. The order of elements in this
array is unde`ned. The function acts on a column or an expression that evaluates to a single value. Returns NULL if
the result contains no rows, or in the event of an error.

As of MySQL 8.0.14, this function executes as a window function if over_clause is present. over_clause is as
described in Section 12.21.2, “Window Function Concepts and Syntax”.

mysql> SELECT o_id, attribute, value FROM t3;


+------+-----------+--------+
| o_id | attribute | value |
+------+-----------+--------+
| 2 | color | red |
| 2 | fabric | silk |
| 3 | color | green |
| 3 | shape | square |
+------+-----------+--------+
4 rows in set (0.00 sec)

mysql> SELECT o_id, JSON_ARRAYAGG(attribute) AS attributes


FROM t3 GROUP BY o_id;
+------+---------------------+
| o_id | attributes |
+------+---------------------+
| 2 | ["color", "fabric"] |
| 3 | ["color", "shape"] |
+------+---------------------+
2 rows in set (0.00 sec)

JSON_OBJECTAGG(key, value) [over_clause]

Takes two column names or expressions as arguments, the `rst of these being used as a key and the second as a
value, and returns a JSON object containing key-value pairs. Returns NULL if the result contains no rows, or in the
event of an error. An error occurs if any key name is NULL or the number of arguments is not equal to 2.

As of MySQL 8.0.14, this function executes as a window function if over_clause is present. over_clause is as
described in Section 12.21.2, “Window Function Concepts and Syntax”.
mysql> SELECT o_id, attribute, value FROM t3;
+------+-----------+--------+
| o_id | attribute | value |
+------+-----------+--------+
| 2 | color | red |
| 2 | fabric | silk |
| 3 | color | green |
| 3 | shape | square |
+------+-----------+--------+
4 rows in set (0.00 sec)

mysql> SELECT o_id, JSON_OBJECTAGG(attribute, value)


FROM t3 GROUP BY o_id;
+------+---------------------------------------+
| o_id | JSON_OBJECTAGG(attribute, value) |
+------+---------------------------------------+
| 2 | {"color": "red", "fabric": "silk"} |
| 3 | {"color": "green", "shape": "square"} |
+------+---------------------------------------+
2 rows in set (0.00 sec)

Duplicate key handling


When the result of this function is normalized, values having duplicate keys are discarded. In keeping with the
MySQL JSON data type speci`cation that does not permit duplicate keys, only the last value encountered is used with
that key in the returned object (“last duplicate key wins”). This means that the result of using this function on
columns from a SELECT can depend on the order in which in the rows are returned, which is not guaranteed. When
used as a window function, if there are duplicate keys within a frame, only the last value for the key is present in the
result. The value for the key from last row in the frame is deterministic if the ORDER BY speci`cation guarantees that
the values have a speci`c order. If not, the resulting value of the key is nondeterministic. Consider the following:

mysql> CREATE TABLE t(c VARCHAR(10), i INT);


Query OK, 0 rows affected (0.03 sec)

mysql> INSERT INTO t VALUES


('key', 3), ('key', 4), ('key', 5);
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0

mysql> SELECT c, i FROM t;


+------+------+
| c | i |
+------+------+
| key | 3 |
| key | 4 |
| key | 5 |
+------+------+
3 rows in set (0.00 sec)

mysql> SELECT JSON_OBJECTAGG(c, i) FROM t;


+----------------------+
| JSON_OBJECTAGG(c, i) |
+----------------------+
| {"key": 5} |
+----------------------+
1 row in set (0.00 sec)

mysql> DELETE FROM t;


Query OK, 3 rows affected (0.00 sec)

mysql> INSERT INTO t VALUES


('key', 3), ('key', 5), ('key', 4);
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0

mysql> SELECT c, i FROM t;


+------+------+
| c | i |
+------+------+
| key | 3 |
| key | 5 |
| key | 4 |
+------+------+
3 rows in set (0.00 sec)

mysql> SELECT JSON_OBJECTAGG(c, i) FROM t;


+----------------------+
| JSON_OBJECTAGG(c, i) |
+----------------------+
| {"key": 4} |
+----------------------+
1 row in set (0.00 sec)

The key chosen from the last query is nondeterministic. If you prefer a particular key ordering, you can
invoke JSON_OBJECTAGG() as a window function by including an OVER clause with an ORDER BY speci`cation to
impose a particular order on frame rows. The following examples show what happens with and without ORDER
BY for a few different frame speci`cations.

Without ORDER BY , the frame is the entire partition:

mysql> SELECT JSON_OBJECTAGG(c, i)


OVER () AS json_object FROM t;
+-------------+
| json_object |
+-------------+
| {"key": 4} |
| {"key": 4} |
| {"key": 4} |
+-------------+
With ORDER BY , where the frame is the default of RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW (in both
ascending and descending order):

mysql> SELECT JSON_OBJECTAGG(c, i)


OVER (ORDER BY i) AS json_object FROM t;
+-------------+
| json_object |
+-------------+
| {"key": 3} |
| {"key": 4} |
| {"key": 5} |
+-------------+
mysql> SELECT JSON_OBJECTAGG(c, i)
OVER (ORDER BY i DESC) AS json_object FROM t;
+-------------+
| json_object |
+-------------+
| {"key": 5} |
| {"key": 4} |
| {"key": 3} |
+-------------+

With ORDER BY and an explicit frame of the entire partition:

mysql> SELECT JSON_OBJECTAGG(c, i)


OVER (ORDER BY i
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
AS json_object
FROM t;
+-------------+
| json_object |
+-------------+
| {"key": 5} |
| {"key": 5} |
| {"key": 5} |
+-------------+

To return a particular key value (such as the smallest or largest), include a LIMIT clause in the appropriate query.
For example:
mysql> SELECT JSON_OBJECTAGG(c, i)
OVER (ORDER BY i) AS json_object FROM t LIMIT 1;
+-------------+
| json_object |
+-------------+
| {"key": 3} |
+-------------+
mysql> SELECT JSON_OBJECTAGG(c, i)
OVER (ORDER BY i DESC) AS json_object FROM t LIMIT 1;
+-------------+
| json_object |
+-------------+
| {"key": 5} |
+-------------+

See Normalization, Merging, and Autowrapping of JSON Values, for additional information and examples.

MAX([DISTINCT] expr) [over_clause]

Returns the maximum value of expr. MAX() may take a string argument; in such cases, it returns the maximum string
value. See Section 8.3.1, “How MySQL Uses Indexes”. The DISTINCT keyword can be used to `nd the maximum of
the distinct values of expr, however, this produces the same result as omitting DISTINCT .

If there are no matching rows, MAX() returns NULL .

This function executes as a window function if over_clause is present. over_clause is as described


in Section 12.21.2, “Window Function Concepts and Syntax”; it cannot be used with DISTINCT .

mysql> SELECT student_name, MIN(test_score), MAX(test_score)


FROM student
GROUP BY student_name;

For MAX(), MySQL currently compares ENUM and SET columns by their string value rather than by the string's relative
position in the set. This differs from how ORDER BY compares them.

MIN([DISTINCT] expr) [over_clause]

Returns the minimum value of expr. MIN() may take a string argument; in such cases, it returns the minimum string
value. See Section 8.3.1, “How MySQL Uses Indexes”. The DISTINCT keyword can be used to `nd the minimum of
the distinct values of expr, however, this produces the same result as omitting DISTINCT .

If there are no matching rows, MIN() returns NULL .

This function executes as a window function if over_clause is present. over_clause is as described


in Section 12.21.2, “Window Function Concepts and Syntax”; it cannot be used with DISTINCT .

mysql> SELECT student_name, MIN(test_score), MAX(test_score)


FROM student
GROUP BY student_name;
For MIN(), MySQL currently compares ENUM and SET columns by their string value rather than by the string's relative
position in the set. This differs from how ORDER BY compares them.

STD(expr) [over_clause]

Returns the population standard deviation of expr. STD() is a synonym for the standard SQL function STDDEV_POP(),
provided as a MySQL extension.

If there are no matching rows, STD() returns NULL .

This function executes as a window function if over_clause is present. over_clause is as described


in Section 12.21.2, “Window Function Concepts and Syntax”.

STDDEV(expr) [over_clause]

Returns the population standard deviation of expr. STDDEV() is a synonym for the standard SQL
function STDDEV_POP(), provided for compatibility with Oracle.

If there are no matching rows, STDDEV() returns NULL .

This function executes as a window function if over_clause is present. over_clause is as described


in Section 12.21.2, “Window Function Concepts and Syntax”.

STDDEV_POP(expr) [over_clause]

Returns the population standard deviation of expr (the square root of VAR_POP()). You can also
use STD() or STDDEV(), which are equivalent but not standard SQL.

If there are no matching rows, STDDEV_POP() returns NULL .

This function executes as a window function if over_clause is present. over_clause is as described


in Section 12.21.2, “Window Function Concepts and Syntax”.

STDDEV_SAMP(expr) [over_clause]

Returns the sample standard deviation of expr (the square root of VAR_SAMP().

If there are no matching rows, STDDEV_SAMP() returns NULL .

This function executes as a window function if over_clause is present. over_clause is as described


in Section 12.21.2, “Window Function Concepts and Syntax”.
          Andrew Francisco
SUM([DISTINCT] expr) [over_clause]

Returns the sum of expr. If the return set has no rows, Dashboard
SUM() returns NULL . The DISTINCT keyword can be used to
Course Options Members-Only Forum About
sum only the distinct values of expr.

If there are no matching rows, SUM() returns NULL .

This function executes as a window function if over_clause is present. over_clause is as described


in Section 12.21.2, “Window Function Concepts and Syntax”; it cannot be used with DISTINCT .

VAR_POP(expr) [over_clause]
Returns the population standard variance of expr. It considers rows as the whole population, not as a sample, so it
has the number of rows as the denominator. You can also use VARIANCE(), which is equivalent but is not standard
SQL.

If there are no matching rows, VAR_POP() returns NULL .

This function executes as a window function if over_clause is present. over_clause is as described


in Section 12.21.2, “Window Function Concepts and Syntax”.

VAR_SAMP(expr) [over_clause]

Returns the sample variance of expr. That is, the denominator is the number of rows minus one.

If there are no matching rows, VAR_SAMP() returns NULL .

This function executes as a window function if over_clause is present. over_clause is as described


in Section 12.21.2, “Window Function Concepts and Syntax”.

VARIANCE(expr) [over_clause]

Returns the population standard variance of expr. VARIANCE() is a synonym for the standard SQL
function VAR_POP(), provided as a MySQL extension.

If there are no matching rows, VARIANCE() returns NULL .

◀︎ Date & Time Functions Reference (Beast) GROUP BY WITH ROLLUP Reference ▶︎


"Success occurs when opportunity meets preparation."

      

You are logged in as Andrew Francisco (Log out)

Copyright © CodingNomads 2022


GROUP BY WITH ROLLUP Reference
The GROUP BY clause permits a WITH ROLLUP modifier that causes summary
output to include extra rows that represent higher-level (that is, super-
aggregate) summary operations. ROLLUP thus enables you to answer
questions at multiple levels of analysis with a single query. For
example,ROLLUP can be used to provide support for OLAP (Online Analytical
Processing) operations.

Suppose that a sales table has year, country, product, and profit columns
for recording sales profitability:

CREATE TABLE sales


(
year INT,
country VARCHAR(20),
product VARCHAR(32),
profit INT
);

To summarize table contents per year, use a simple GROUP BY like this:

mysql> SELECT year, SUM(profit) AS profit


FROM sales
GROUP BY year;
+------+--------+
| year | profit |
+------+--------+
| 2000 | 4525 |
| 2001 | 3010 |
+------+--------+
The output shows the total (aggregate) profit for each year. To also
determine the total profit summed over all years, you must add up the
individual values yourself or run an additional query. Or you can use ROLLUP,
which provides both levels of analysis with a single query. Adding aWITH
ROLLUP modifier to the GROUP BY clause causes the query to produce another
(super-aggregate) row that shows the grand total over all year values:

mysql> SELECT year, SUM(profit) AS profit


FROM sales
GROUP BY year WITH ROLLUP;
+------+--------+
| year | profit |
+------+--------+
| 2000 | 4525 |
| 2001 | 3010 |
| NULL | 7535 |
+------+--------+

The NULL value in the year column identifies the grand total super-aggregate
line.

ROLLUP has a more complex effect when there are multiple GROUP
BY columns. In this case, each time there is a change in value in any but the
last grouping column, the query produces an extra super-aggregate
summary row.

For example, without ROLLUP, a summary of the sales table based


on year, country, and product might look like this, where the output
indicates summary values only at the year/country/product level of analysis:

mysql> SELECT year, country, product, SUM(profit) AS profit


FROM sales
GROUP BY year, country, product;
+------+---------+------------+--------+
| year | country | product | profit |
+------+---------+------------+--------+
| 2000 | Finland | Computer | 1500 |
| 2000 | Finland | Phone | 100 |
| 2000 | India | Calculator | 150 |
| 2000 | India | Computer | 1200 |
| 2000 | USA | Calculator | 75 |
| 2000 | USA | Computer | 1500 |
| 2001 | Finland | Phone | 10 |
| 2001 | USA | Calculator | 50 |
| 2001 | USA | Computer | 2700 |
| 2001 | USA | TV | 250 |
+------+---------+------------+--------+

With ROLLUP added, the query produces several extra rows:

mysql> SELECT year, country, product, SUM(profit) AS profit


FROM sales
GROUP BY year, country, product WITH ROLLUP;
+------+---------+------------+--------+
| year | country | product | profit |
+------+---------+------------+--------+
| 2000 | Finland | Computer | 1500 |
| 2000 | Finland | Phone | 100 |
| 2000 | Finland | NULL | 1600 |
| 2000 | India | Calculator | 150 |
| 2000 | India | Computer | 1200 |
| 2000 | India | NULL | 1350 |
| 2000 | USA | Calculator | 75 |
| 2000 | USA | Computer | 1500 |
| 2000 | USA | NULL | 1575 |
| 2000 | NULL | NULL | 4525 |
| 2001 | Finland | Phone | 10 |
| 2001 | Finland | NULL | 10 |
| 2001 | USA | Calculator | 50 |
| 2001 | USA | Computer | 2700 |
| 2001 | USA | TV | 250 |
| 2001 | USA | NULL | 3000 |
| 2001 | NULL | NULL | 3010 |
| NULL | NULL | NULL | 7535 |
+------+---------+------------+--------+

Now the output includes summary information at four levels of analysis, not
just one:

Following each set of product rows for a given year and country, an
extra super-aggregate summary row appears showing the total for all
products. These rows have the product column set to NULL.

Following each set of rows for a given year, an extra super-aggregate


summary row appears showing the total for all countries and products.
These rows have the country and products columns set to NULL.

Finally, following all other rows, an extra super-aggregate summary row


appears showing the grand total for all years, countries, and products.
This row has the year, country, and products columns set to NULL.

The NULL indicators in each super-aggregate row are produced when the row
is sent to the client. The server looks at the columns named in the GROUP
BY clause following the leftmost one that has changed value. For any column
in the result set with a name that matches any of those names, its value is
set to NULL. (If you specify grouping columns by column position, the server
identifies which columns to set to NULL by position.)

Because the NULL values in the super-aggregate rows are placed into the
result set at such a late stage in query processing, you can test them
asNULL values only in the select list or HAVING clause. You cannot test them
as NULL values in join conditions or the WHERE clause to determine which rows
to select. For example, you cannot add WHERE product IS NULL to the query
to eliminate from the output all but the super-aggregate rows.

The NULL values do appear as NULL on the client side and can be tested as
such using any MySQL client programming interface. However, at this point,
you cannot distinguish whether a NULL represents a regular grouped value or
a super-aggregate value. To test the distinction, use theGROUPING() function,
described later.

Previously, MySQL did not allow the use of DISTINCT or ORDER BY in a query
having a WITH ROLLUP option. This restriction is lifted in MySQL 8.0.12 and
later. (Bug #87450, Bug #86311, Bug #26640100, Bug #26073513)

For GROUP BY ... WITH ROLLUP queries, to test whether NULL values in the
result represent super-aggregate values, the GROUPING() function is available
for use in the select list, HAVING clause, and (as of MySQL 8.0.12) ORDER
BY clause. For example, GROUPING(year) returns 1 when NULL in
the year column occurs in a super-aggregate row, and 0 otherwise.
Similarly, GROUPING(country) and GROUPING(product) return 1 for super-
aggregate NULL values in the country and product columns, respectively:

mysql> SELECT
year, country, product, SUM(profit) AS profit,
GROUPING(year) AS grp_year,
GROUPING(country) AS grp_country,
GROUPING(product) AS grp_product
FROM sales
GROUP BY year, country, product WITH ROLLUP;
+------+---------+------------+--------+----------+-------------+-------------+
| year | country | product | profit | grp_year | grp_country | grp_product |
+------+---------+------------+--------+----------+-------------+-------------+
| 2000 | Finland | Computer | 1500 | 0 | 0 | 0 |
| 2000 | Finland | Phone | 100 | 0 | 0 | 0 |
| 2000 | Finland | NULL | 1600 | 0 | 0 | 1 |
| 2000 | India | Calculator | 150 | 0 | 0 | 0 |
| 2000 | India | Computer | 1200 | 0 | 0 | 0 |
| 2000 | India | NULL | 1350 | 0 | 0 | 1 |
| 2000 | USA | Calculator | 75 | 0 | 0 | 0 |
| 2000 | USA | Computer | 1500 | 0 | 0 | 0 |
| 2000 | USA | NULL | 1575 | 0 | 0 | 1 |
| 2000 | NULL | NULL | 4525 | 0 | 1 | 1 |
| 2001 | Finland | Phone | 10 | 0 | 0 | 0 |
| 2001 | Finland | NULL | 10 | 0 | 0 | 1 |
| 2001 | USA | Calculator | 50 | 0 | 0 | 0 |
| 2001 | USA | Computer | 2700 | 0 | 0 | 0 |
| 2001 | USA | TV | 250 | 0 | 0 | 0 |
| 2001 | USA | NULL | 3000 | 0 | 0 | 1 |
| 2001 | NULL | NULL | 3010 | 0 | 1 | 1 |
| NULL | NULL | NULL | 7535 | 1 | 1 | 1 |
+------+---------+------------+--------+----------+-------------+-------------+

Instead of displaying the GROUPING() results directly, you can


use GROUPING() to substitute labels for super-aggregate NULL values:

mysql> SELECT
IF(GROUPING(year), 'All years', year) AS year,
IF(GROUPING(country), 'All countries', country) AS country,
IF(GROUPING(product), 'All products', product) AS product,
SUM(profit) AS profit
FROM sales
GROUP BY year, country, product WITH ROLLUP;
+-----------+---------------+--------------+--------+
| year | country | product | profit |
+-----------+---------------+--------------+--------+
| 2000 | Finland | Computer | 1500 |
| 2000 | Finland | Phone | 100 |
| 2000 | Finland | All products | 1600 |
| 2000 | India | Calculator | 150 |
| 2000 | India | Computer | 1200 |
| 2000 | India | All products | 1350 |
| 2000 | USA | Calculator | 75 |
| 2000 | USA | Computer | 1500 |
| 2000 | USA | All products | 1575 |
| 2000 | All countries | All products | 4525 |
| 2001 | Finland | Phone | 10 |
| 2001 | Finland | All products | 10 |
| 2001 | USA | Calculator | 50 |
| 2001 | USA | Computer | 2700 |
| 2001 | USA | TV | 250 |
| 2001 | USA | All products | 3000 |
| 2001 | All countries | All products | 3010 |
| All years | All countries | All products | 7535 |
+-----------+---------------+--------------+--------+

With multiple expression arguments, GROUPING() returns a result


representing a bitmask the combines the results for each expression, with
the lowest-order bit corresponding to the result for the rightmost expression.
For example, GROUPING(year, country, product) is evaluated like this:

result for GROUPING(product)


+ result for GROUPING(country) << 1
+ result for GROUPING(year) << 2

The result of such a GROUPING() is nonzero if any of the expressions


represents a super-aggregate NULL, so you can return only the super-
aggregate rows and filter out the regular grouped rows like this:

mysql> SELECT year, country, product, SUM(profit) AS profit


FROM sales
GROUP BY year, country, product WITH ROLLUP
HAVING GROUPING(year, country, product) <> 0;
+------+---------+---------+--------+
| year | country | product | profit |
+------+---------+---------+--------+
| 2000 | Finland | NULL | 1600 |
| 2000 | India | NULL | 1350 |
| 2000 | USA | NULL | 1575 |
| 2000 | NULL | NULL | 4525 |
| 2001 | Finland | NULL | 10 |
| 2001 | USA | NULL | 3000 |
| 2001 | NULL | NULL | 3010 |
| NULL | NULL | NULL | 7535 |
+------+---------+---------+--------+

The sales table contains no NULL values, so all NULL values in a ROLLUP result
represent super-aggregate values. When the data set
contains NULLvalues, ROLLUP summaries may contain NULL values not only in
super-aggregate rows, but also in regular grouped rows. GROUPING() enables
these to be distinguished. Suppose that table t1 contains a simple data set
with two grouping factors for a set of quantity values, where NULL indicates
something like “other” or “unknown”:

mysql> SELECT * FROM t1;


+------+-------+----------+
| name | size | quantity |
+------+-------+----------+
| ball | small | 10 |
| ball | large | 20 |
| ball | NULL | 5 |
| hoop | small | 15 |
| hoop | large | 5 |
| hoop | NULL | 3 |
+------+-------+----------+

A simple ROLLUP operation produces these results, in which it is not so easy


to distinguish NULL values in super-aggregate rows from NULL values in
regular grouped rows:

mysql> SELECT name, size, SUM(quantity) AS quantity


FROM t1
GROUP BY name, size WITH ROLLUP;
+------+-------+----------+
| name | size | quantity |
+------+-------+----------+
| ball | NULL | 5 |
| ball | large | 20 |
| ball | small | 10 |
| ball | NULL | 35 |
| hoop | NULL | 3 |
| hoop | large | 5 |
| hoop | small | 15 |
| hoop | NULL | 23 |
| NULL | NULL | 58 |
+------+-------+----------+

Using GROUPING() to substitute labels for the super-aggregate NULL values


makes the result easier to interpret:

mysql> SELECT
IF(GROUPING(name) = 1, 'All items', name) AS name,
IF(GROUPING(size) = 1, 'All sizes', size) AS size,
SUM(quantity) AS quantity
FROM t1
GROUP BY name, size WITH ROLLUP;
+-----------+-----------+----------+
| name | size | quantity |
+-----------+-----------+----------+
| ball | NULL | 5 |
| ball | large | 20 |
| ball | small | 10 |
| ball | All sizes | 35 |
| hoop | NULL | 3 |
| hoop | large | 5 |
| hoop | small | 15 |
| hoop | All sizes | 23 |
| All items | All sizes | 58 |
+-----------+-----------+----------+

Other Considerations When using ROLLUP

The following discussion lists some behaviors specific to the MySQL


implementation of ROLLUP.

Prior to MySQL 8.0.12, when you use ROLLUP, you cannot also use an ORDER
BY clause to sort the results. In other words, ROLLUP and ORDER BYwere
mutually exclusive in MySQL. However, you still have some control over sort
order. To work around the restriction that prevents using ROLLUPwith ORDER
BY and achieve a specific sort order of grouped results, generate the
grouped result set as a derived table and apply ORDER BY to it. For example:

mysql> SELECT * FROM


(SELECT year, SUM(profit) AS profit
FROM sales GROUP BY year WITH ROLLUP) AS dt
ORDER BY year DESC;
+------+--------+
| year | profit |
+------+--------+
| 2001 | 3010 |
| 2000 | 4525 |
| NULL | 7535 |
+------+--------+

As of MySQL 8.0.12, ORDER BY and ROLLUP can be used together, which


enables the use of ORDER BY and GROUPING() to achieve a specific sort order
of grouped results. For example:

mysql> SELECT year, SUM(profit) AS profit


FROM sales
GROUP BY year WITH ROLLUP
ORDER BY GROUPING(year) DESC;
+------+--------+
| year | profit |
+------+--------+
| NULL | 7535 |
| 2000 | 4525 |
| 2001 | 3010 |
+------+--------+

In both cases, the super-aggregate summary rows sort with the rows from
which they are calculated, and their placement depends on sort order (at the
end for ascending sort, at the beginning for descending sort).

LIMIT can be used to restrict the number of rows returned to the


client. LIMIT is applied after ROLLUP, so the limit applies against the extra
rows added by ROLLUP. For example:

mysql> SELECT year, country, product, SUM(profit) AS profit


FROM sales
GROUP BY year, country, product WITH ROLLUP
LIMIT 5;
+------+---------+------------+--------+
| year | country | product | profit |
+------+---------+------------+--------+
| 2000 | Finland | Computer | 1500 |
| 2000 | Finland | Phone | 100 |
| 2000 | Finland | NULL | 1600 |
| 2000 | India | Calculator | 150 |
| 2000 | India | Computer | 1200 |
+------+---------+------------+--------+

Using LIMIT with ROLLUP may produce results that are more difficult to
interpret, because there is less context for understanding the super-
aggregate rows.

A MySQL extension permits a column that does not appear in the GROUP
BY list to be named in the select list. (For information about nonaggregated
columns and GROUP BY, see Section 12.20.3, “MySQL Handling of GROUP
BY”.) In this case, the server is free to choose any value from this
nonaggregated column in summary rows, and this includes the extra rows
added by WITH ROLLUP. For example, in the following query, country is a
nonaggregated column that does not appear in the GROUP BY list and values
chosen for this column are nondeterministic:

mysql> SELECT year, country, SUM(profit) AS profit


FROM sales
GROUP BY year WITH ROLLUP;
+------+---------+--------+
| year | country | profit |
+------+---------+--------+
| 2000 | India | 4525 |
| 2001 | USA | 3010 |
| NULL | USA | 7535 |
+------+---------+--------+

This behavior is permitted when the ONLY_FULL_GROUP_BY SQL mode is not


enabled. If that mode is enabled, the server rejects the query as illegal
because country is not listed in the GROUP BY clause.
With ONLY_FULL_GROUP_BY enabled, you can still execute the query by using
theANY_VALUE() function for nondeterministic-value columns:
mysql> SELECT year, ANY_VALUE(country) AS country, SUM(profit) AS profit
FROM sales
GROUP BY year WITH ROLLUP;
+------+---------+--------+
| year | country | profit |
+------+---------+--------+
| 2000 | India | 4525 |
| 2001 | USA | 3010 |
| NULL | USA | 7535 |
+------+---------+--------+

You might also like