© Charles Bell 2018
Charles BellIntroducing the MySQL 8 Document Storehttps://doi.org/10.1007/978-1-4842-2725-1_2

2. Getting Started with MySQL

Charles Bell1 
(1)
Warsaw, Virginia, USA
 

Perhaps you’ve never used a database system before or maybe you’ve used one as a user but have never had any need to set up one from scratch. Or perhaps you’ve decided to discover what all the fuss is about database systems in general. Or maybe you’ve used MySQL only as a developer never seeing how to setup and configure the server.

In this chapter, I present a short introduction to MySQL in the general SQL interface sense (traditional MySQL). Not only will you see how MySQL 8 is setup, you will also be introduced to some of the basics of the SQL interface, which is necessary and indeed required to fully manage a MySQL server. That is, the new shell, X protocol, X DevAPI, and the features that build on it but do not offer a complete mechanism for managing the server; you will need to continue to use SQL commands for those tasks.

So, although MySQL 8 offers an excellent NoSQL interface for both applications and interactive sessions, you still need to know to use the SQL interface. Fortunately, I present the basics in a short primer on how to use MySQL. Let’s begin with a brief foray into what MySQL is and what it can do for us.

Getting to Know MySQL

MySQL is the world’s most popular open source database system for many excellent reasons. First, it is open source, which means anyone can use it for a wide variety of tasks for free. Best of all, MySQL is included in many platform repositories this makes it easy to get and install. If your platform doesn’t include MySQL in the repository (such as aptitude), you can download it from the MySQL web site ( http://dev.mysql.com ).

The Oracle Corporation owns MySQL. Oracle obtained MySQL through an acquisition of Sun Microsystems, which acquired MySQL from its original owners, MySQL AB. Despite fears to the contrary, Oracle has shown excellent stewardship of MySQL by continuing to invest in the evolution and development of new features as well as faithfully maintaining its open source heritage. Although Oracle also offers commercial licenses of MySQL—just as its prior owners did in the past—MySQL is still open source and available to everyone.

Is Open Source Really Free?

Open source software grew from a conscious resistance to the corporate property mind-set. Richard Stallman is credited as the father of the free software movement who pioneered a licensing mechanism to help protect ownership of software and yet make the use of the software and to some degree its revision free to all. The goal was to reestablish a community of developers cooperating with a single imperative: to guarantee freedom rather than restrict it.

This ultimately led to the invention of some cleverly worded (read legally binding) licensing agreements that permits the code to be copied and modified without restriction, states that derivative works (the modified copies) must be distributed under the same license as the original version without any additional restrictions. One such license (created by Stallman) is called the GNU Public License (GPL). This is the license that is used by Oracle to license MySQL and as such it is indeed free for anyone to use.

However, GPL and similar licenses are intended to guarantee freedom to use, modify, and distribute; most never intended “free” to mean “no cost” or “free to a good home.” To counter this misconception, the Open Source Initiative (OSI) formed and later adopted and promoted the phrase open source to describe the freedoms guaranteed by the GPL license. For more information about open source software and the GPL, visit www.opensource.org .

MySQL runs as a background process (or as a foreground process if you launch it from the command line) on your system. As with most database systems, MySQL supports structured query language (SQL). You can use SQL to create databases and objects (using data definition language; DDL), write or change data (using data manipulation language; DML), and execute various commands for managing the server.

How Do I Connect to MySQL?

We have already seen a brief look at the new MySQL Shell for connecting to and working with MySQL servers, the AdminAPI to configure an InnoDB Cluster, and the X DevAPI to access with data. However, there is another client that has been around in MySQL for decades. It is an application named mysql, which enables you to connect to and run SQL commands on the server. It is interesting that this MySQL client was originally named the MySQL monitor but has long since been called simply the “MySQL client,” terminal monitor, or even the MySQL command window.

New Default Authentication

Prior to MySQL version 8.0.4, the default authentication mechanism used an authentication plugin called the mysql_native_password plugin, which used the SHA1 algorithm. This mechanism was fast and did not require an encrypted connection. However, since the National Institute of Standards and Technology (NIST) suggested that they should stop using the SHA1 algorithm; Oracle has changed the default authentication plugin in MySQL version 8.0.4 to the cachin_sha2_password plugin.

The consequences of this change should not be an issue to any organizations that install MySQL 8.0.4 but may be a concern for those upgrading to 8.0.4 or those who have older installations of MySQL. The biggest issue is that the older client utilities, such as the mysql client from version 5.7, may not be able to connect to newer installations of MySQL 8.0.4 or later.

Although you can change your MySQL 8.0.4 to use the older authentication mechanism, it is not recommended and you should upgrade all your client tools to 8.0.4 or later to work with the latest versions of MySQL.

If you would like to learn more about the changes including why Oracle made the change and the advantages for users, see https://mysqlserverteam.com/mysql-8-0-4-newdefault-authentication-plugin-caching_sha2_password/.

To connect to the server using the MySQL client (mysql), you must specify a user account and the server to which you want to connect. If you are connecting to a server on the same machine, you can omit the server information (host and port) because they default to localhost on port 3306. The user is specified using the --user (or -u) option. You can specify the password for the user on the command, but the more secure practice is to specify --password (or -p), and the client will prompt you for the password. If you do specify the password on the command line, you will be prompted with a warning encouraging you to not use that practice.

Using the mysql client on the same machine without the --host (or -h) and --port option does not use a network connection. If you want to connect using a network connection or want to connect using a different port, you must use the loopback address. For example, to connect to a server running on port 3307 on the same machine, use the command mysql -uroot -p –h127.0.0.1 --port=3307. Listing 2-1 shows examples of several SQL commands in action using the mysql client.

Tip

To see a list of the commands available in the client, type help; and press Enter at the prompt.

$ mysql -uroot -proot -h 127.0.0.1 --port=3307
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or g.
Your MySQL connection id is 14
Server version: 8.0.11 MySQL Community Server (GPL)
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.
mysql> CREATE DATABASE greenhouse;
Query OK, 1 row affected (0.00 sec)
mysql> CREATE TABLE greenhouse.plants (plant_name char(50), sensor_value int, sensor_event timestamp);
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO greenhouse.plants VALUES ('living room', 23, NULL);
Query OK, 1 row affected (0.01 sec)
mysql> SELECT * FROM greenhouse.plants;
+-------------+--------------+--------------+
| plant_name  | sensor_value | sensor_event |
+-------------+--------------+--------------+
| living room |           23 | NULL         |
+-------------+--------------+--------------+
1 row in set (0.00 sec)
mysql> SET @@global.server_id = 106;
Query OK, 0 rows affected (0.00 sec)
mysql> quit
Bye
Listing 2-1

Commands Using the mysql Client

In this example, you see DDL in the form of the CREATE DATABASE and CREATE TABLE statements, DML in the form of the INSERT and SELECT statements, and a simple administrative command to set a global server variable. Next you see the creation of a database and a table to store the data, the addition of a row in the table, and finally the retrieval of the data in the table. Notice how I used capital letters for SQL command keywords. This is a common practice and helps make the SQL commands easier to read and easier to find user-supplied options or data.

Tip

You can exit the MySQL client by typing the command quit. On Linux and Unix systems, you can press Ctrl+D to exit the client.

A great many commands are available in MySQL. Fortunately, you need master only a few of the more common ones. The following are the commands you will use most often. The portions enclosed in <> indicate user-supplied components of the command, and […] indicates that additional options are needed.
  • CREATE DATABASE <database_name>: creates a database

  • USE <database>: sets the default database (not an SQL command)

  • CREATE TABLE <table_name> [...]: creates a table or structure to store data

  • INSERT INTO <table_name> [...]: adds data to a table

  • UPDATE [...]: changes one or more values for a specific row

  • DELETE FROM <table_name> [...]: removes data from a table

  • SELECT [...]: retrieves data (rows) from the table

  • SHOW [...]: shows a list of the objects

Note

You must terminate each command with a semicolon (;) or G.

Although this list is only a short introduction and not a complete syntax guide, there is an excellent online MySQL reference manual that explains every command (and much more) in greater detail. You should refer to the online MySQL reference manual whenever you have a question about anything in MySQL. You can find it at http://dev.mysql.com/doc/ .

One of the more interesting commands shown allows you to see a list of objects. For example, you can see the databases with SHOW DATABASES , a list of tables (once you change to a database) with SHOW TABLES , and even the permissions for users with SHOW GRANTS. I find myself using these commands frequently.

If you think that there is a lot more to MySQL than a few simple commands, you are correct. Despite its ease of use and fast start-up time, MySQL is a full-fledged relational database management system (RDBMS). There is much more to it than you’ve seen here. For more information about MySQL, including all the advanced features, see the online MySQL reference manual.

How to Get and Install MySQL

The MySQL server is available for a variety of platforms including most Linux and Unix platforms, Mac OS X, and Windows. As of this writing, MySQL 8 was not a GA release and as such only offered as a development milestone release (DMR). DMRs are an excellent way for you to try out new versions and features before they are released as GA. Generally, non-GA releases are considered developmental or in the case of early release candidates such as MySQL 8.0.4, a release candidate. Thus, you should not install and use DMR releases on your production machines.

To download GA releases of MySQL 8, visit http://dev.mysql.com/downloads/ and click Community, then MySQL Community. You can also click on the link near the bottom of the downloads page named Community (GPL) Downloads, then click MySQL Community Server . This is the GPLv2 license of MySQL. The page will automatically detect your operating system. If you want to download for another platform, you can select it from the dropdown list.

The download page will list several files for download. Depending on your platform, you may see several options including compressed files, source code, and installation packages. Most will choose the installation package for installation on a laptop or desktop computer. Figure 2-1 shows an example of the various download options for macOS platforms.
../images/432285_1_En_2_Chapter/432285_1_En_2_Fig1_HTML.png
Figure 2-1

Download page for macOS

One of the most popular platforms is Microsoft Windows. Oracle has provided a special installation packaging for Windows named the Windows Installer. This package includes all the MySQL products available under the community license including MySQL Server, Workbench, Utilities, and all of the available connectors (program libraries for connecting to MySQL). This makes installing on Windows a one-stop, one-installation affair. Figure 2-2 shows the download page for the Windows installer.
../images/432285_1_En_2_Chapter/432285_1_En_2_Fig2_HTML.jpg
Figure 2-2

Download page for Windows Installer

However, you should note that some of the more advanced features and some of the plugins that also are in a developer milestone release (DMR) state may not be included in the Windows Installer. Thus, you should consider installing by using the server package. We see these below the Windows Installer download link in Figure 2-2. You can choose either the Windows Installer 32- or 64-bit installation. Note that the package may be nothing more than a .zip file containing the server code. In this case, you may need to either run the server from the unzipped folder or do a local, manual install.

Fortunately, as MySQL 8 matures, more packaging options will become available allowing you to use a semi-automated installation mechanism. Let’s see one of those in action. In this scenario, we will install MySQL 8 on a macOS Sierra machine. In this case, I have downloaded the file mysql-8.0.11-macos10.13-x86_64.dmg, which is a compressed file containing a package installation program named mysql-8.0.11-macos10.13-x86_64.pkg for macOS. Once I launch the installer, the first step is agreeing to the license. Figure 2-3 shows the license agreement panel of the installation dialog.
../images/432285_1_En_2_Chapter/432285_1_En_2_Fig3_HTML.jpg
Figure 2-3

License agreement

The license shown is the GPLv2 license for the community edition. You can read the license and when ready, click Continue. You will see an acceptance dialog open, which will give you another chance to read the license.1 When you’re ready to accept the license, click Accept. Figure 2-4 shows the license acceptance dialog.
../images/432285_1_En_2_Chapter/432285_1_En_2_Fig4_HTML.jpg
Figure 2-4

Accept license

The next panel displays the setup or installation type. Early releases such as this version may not show any installation types to choose from. If you run the Windows Installer, you will see several options. For most platforms, the default installation type is all you will need to get started. Figure 2-5 shows the installation type panel. When ready, click Install.
../images/432285_1_En_2_Chapter/432285_1_En_2_Fig5_HTML.jpg
Figure 2-5

Installation type

The installation may ask you to authorize the installation and once done, it will proceed rather quickly installing MySQL in the /usr/local/mysql folder (e.g., on Sierra).

If this is the first time you’ve installed MySQL 8, you will see a dialog that displays the default password for the root account. This was a change made in MySQL 5.7, which eliminated anonymous accounts and made server installations more secure. You should take note of this password, as it is a general random collection of characters and symbols that you won’t be able to guess. Figure 2-6 shows one such example dialog.
../images/432285_1_En_2_Chapter/432285_1_En_2_Fig6_HTML.jpg
Figure 2-6

Root password notice

Figure 2-7 shows how you can recover this dialog on macOS from the notification center if you, like me, tend to dismiss dialogs without fully reading them.2
../images/432285_1_En_2_Chapter/432285_1_En_2_Fig7_HTML.jpg
Figure 2-7

Root password notice in macOS notification center

Once complete, you will get a completion dialog, which you can safely dismiss. Finally, you will be asked whether you want to keep the installation file (the .dmg) or delete it. If you are experimenting with MySQL 8 or think you may want to install it some other place, do not delete the file.

Tip

It may be a good idea to add the path /usr/local/mysql/bin to your default PATH variable if it is not already set. It makes starting the MySQL client tools much easier.

As you may have surmised, you need to change the root password as your first action after installation. Doing so is easy. Just open the MySQL client (mysql) and issue the following SQL statement. Because we installed the server in the default location, we can start the client with only the user and password prompts like this: mysql -uroot -p. The client will prompt you for the password.

SET PASSWORD="NEW_PASSWORD_GOES_HERE";

If you get a message that you cannot connect to the server, it may mean the server has not been started. You can start the server on macOS with the following command.

sudo launchctl load -F /Library/LaunchDaemons/com.oracle.oss.mysql.mysqld.plist

Note

When installing MySQL 8 on Windows, be sure to check the box marked Enable X Protocol/MySQL as a Document Store during the installation to ensure the X Plugin and X Protocol are enabled.

Okay, now that we have the MySQL 8 server installed, we can begin configuring the server for use. You could install the MySQL Shell at this point, but we will explore how to install the MySQL Shell in more detail in Chapter 4.

Configuring and Managing Access to MySQL

Now that you know how to install MySQL, let’s briefly discuss how to configure MySQL and how to grant access to the server (and databases) to others as well as how to setup the X Plugin (the key component to enable the document store). We begin with a look at the configuration file used to define the behavior and configure options in MySQL.

Configuration Files

The primary way to configure start-up options and variables in MySQL is accomplished using a text file named my.cnf (or my.ini on Windows). This file is normally located on Posix systems in the /etc folder. For example, on macOS, the file is named /etc/my.cnf. Listing 2-2 shows the first few dozen lines from a typical MySQL configuration file.

# Example MySQL config file for small systems.
#
# This is for a system with little memory (<= 64M) where MySQL is only used
# from time to time and it's important that the mysqld daemon
# doesn't use much resources.
#
# MySQL programs look for option files in a set of
# locations which depend on the deployment platform.
# You can copy this option file to one of those
# locations. For information about these locations, see:
# http://dev.mysql.com/doc/mysql/en/option-files.html
#
# In this file, you can use all long options that a program supports.
# If you want to know which options a program supports, run the program
# with the "--help" option.
# The following options will be passed to all MySQL clients
[client]
port            = 3306
socket          = /tmp/mysql.sock
# Here follows entries for some specific programs
# The MySQL server
[mysqld]
port            = 3306
socket          = /tmp/mysql.sock
skip-external-locking
key_buffer_size = 16K
max_allowed_packet = 1M
table_open_cache = 4
sort_buffer_size = 64K
read_buffer_size = 256K
read_rnd_buffer_size = 256K
net_buffer_length = 2K
thread_stack = 1024K
...
innodb_log_file_size = 5M
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 50
innodb_log_files_in_group = 2
slow-query-log
general-log
...
Listing 2-2

MySQL Configuration File Excerpt

Note that we have settings grouped by section defined using square brackets []. For example, we see a section named [client], which is used to define options for any MySQL client that reads the configuration file. Likewise, we see a section named [mysqld], which applies to the server process (because the executable is named mysqld). Note that we also see settings for basic options like port, socket, and so forth. However, we also can use the configuration file to set options for InnoDB, replication, and more.

I recommend that you locate and browse the configuration file for your installation so you can see the options and their values. If you encounter a situation in which you need to change an option—say to test the effect or perhaps to experiment—you can use the SET command to change values either as a global setting (affects all connections) or a session setting (applies only to the current connection).

However, if you change a global setting that is also in the configuration file, the value (state) will remain only until the server is rebooted. Thus, if you want to keep global changes, you should consider placing them in the configuration file.

On the other hand, setting a value at the session level could be beneficial for a limited time or may be something you want to do only for a specific task. For example, the following turns off the binary log, executes a SQL command, and then turns the binary log back on. The following is a simple but profound example of how to perform actions on a server that participate in replication without having the actions affect other servers.3

SET sql_log_bin=0;
CREATE USER 'hvac_user1'@'%' IDENTIFIED BY 'secret';
SET sql_log_bin=1;

For more information about the configuration file and how to use it to configure MySQL 8 including using multiple option files and where the files exist on each platform, see the section, “Using Option Files” in the online MySQL reference manual ( http://dev.mysql.com/doc/refman/8.0/en/ ).

Creating Users and Granting Access

There are two additional administrative operations you need to understand before working with MySQL: creating user accounts and granting access to databases. MySQL can perform both with the GRANT statement, which automatically creates a user if one does not exist. But the more pedantic method is first to issue a CREATE USER command followed by one or more GRANT commands. For example, the following shows the creation of a user named hvac_user1 and grants the user access to the database room_temp:

CREATE USER 'hvac_user1'@'%' IDENTIFIED BY 'secret';
GRANT SELECT, INSERT, UPDATE ON room_temp.* TO 'hvac_user1'@'%';

The first command creates the user named hvac_user1, but the name also has an @ followed by another string. This second string is the host name of the machine with which the user is associated. That is, each user in MySQL has both a user name and a host name, in the form user@host, to uniquely identify them. That means the user and host [email protected] and the user and host [email protected] are not the same. However, the % symbol can be used as a wildcard to associate the user with any host. The IDENTIFIED BY clause sets the password for the user.

A Note About Security

It is always a good idea to create a user for your application that does not have full access to the MySQL system. This is so you can minimize any accidental changes and also to prevent exploitation. For example, it is recommended that you create a user with access only to those databases in which you store (or retrieve) data.

Also be careful about using the wildcard % for the host. Although it makes it easier to create a single user and let the user access the database server from any host, it also makes it much easier for someone bent on malice to access your server (once they discover the password).

The second command allows access to databases. There are many privileges that you can give a user. The example shows the most likely set that you would want to give a user of a sensor network database: read (SELECT), add data (INSERT), and change data (UPDATE). See the online MySQL reference manual for more about security and account access privileges.

The command also specifies a database and objects where to grant the privilege. Thus, it is possible to give a user read (SELECT) privileges to some tables and write (INSERT, UPDATE) privileges to other tables. This example gives the user access to all objects (tables, views, and so on) in the room_temp database.

As mentioned, you can combine these two commands into a single command. You are likely to see this form more often in the literature. The following shows the combined syntax. In this case, all you need to do is add the IDENTIFIED BY clause to the GRANT statement. Cool!

GRANT SELECT, INSERT, UPDATE ON room_temp.* TO 'hvac_user1'@'%' IDENTIFIED BY 'secret';

Next, let’s see how to configure the server for use with the document store; to be more specific by installing the X Plugin.

Configuring the Document Store

The last thing you want to do before exploring the MySQL Document Store is to ensure the X Plugin is installed. If you installed MySQL on Windows, and you chose to enable the Enable X Protocol/MySQL as a Document Store, you can skip this step. However, other platforms may require configuring the server for use with the document store.

To enable the X Protocol on older MySQL servers, we need to install the X Plugin. The X Plugin is named MySQLX and is easily installed with the following command. The INSTALL PLUGIN command takes the name of the plugin (mysqlx) and the name of the shared library. By convention, shared libraries are named the same as the plugin with the .so suffix (Windows machines use .dll).

INSTALL PLUGIN mysqlx SONAME 'mysqlx.so';

Note

MySQL release 8.0.11 and later enable the X Plugin by default.

You can check to see what plugins are enabled using the following command. You will see all plugins installed and their current state. Note that we see the X Plugin in the list as enabled.

mysql> SHOW PLUGINS G
*************************** 1. row ***************************
   Name: keyring_file
 Status: ACTIVE
   Type: KEYRING
Library: keyring_file.so
License: GPL
*************************** 2. row ***************************
   Name: binlog
 Status: ACTIVE
   Type: STORAGE ENGINE
Library: NULL
License: GPL
...
*************************** 43. row ***************************
   Name: mysqlx
 Status: ACTIVE
   Type: DAEMON
Library: mysqlx.so
License: GPL
43 rows in set (0.00 sec)

That’s all there is to it. Once enabled, your server will communicate with the X Protocol to the MySQL Shell or any other system, service, or application that uses the X Protocol.

If there is a need to uninstall the X Plugin, you can do so with the following command:

UNINSTALL PLUGIN mysqlx;

In the following section, I take a longer tour of the MySQL server, to show how to use basic SQL commands. There will be more about the document store in later chapters.

A MySQL Primer

If you have never used a database system, learning and mastering the system requires training, experience, and a good deal of perseverance. Chief among the knowledge needed to become proficient is how to use the common SQL commands and concepts. This section completes the primer on MySQL by introducing the most common MySQL commands and concepts as a foundation for learning how to use the document store.

Note

Rather than regurgitate the online MySQL reference manual, this section introduces the commands and concepts at a higher level. If you decide to use any of the commands or concepts, please refer to the online MySQL reference manual for additional details, complete command syntax, and additional examples.

This section reviews the most common SQL and MySQL-specific commands that you will need to know to get the most out of your MySQL server databases. Although you have already seen some of these in action, this section provides additional information to help you use them.

One important rule to understand is user-supplied variable names are case sensitive and obey case sensitivity of the host platform. For example, resolving last_name versus Last_Name is not consistent across platforms. That is, case-sensitivity behavior is different on Windows than it is on macOS. Check the online MySQL reference manual for your platform to see how case sensitivity affects user-supplied variables.

Creating Databases and Tables

The most basic commands you will need to learn and master are the CREATE DATABASE and CREATE TABLE commands. Recall that database servers such as MySQL allow you to create any number of databases that you can add tables and store data in a logical manner.

To create a database, use CREATE DATABASE followed by a name for the database. If you are using the MySQL client, you must use the USE command to switch to a specific database. The client focus is the latest database specified either at startup (on the command line) or via the USE command.

You can override this by referencing the database name first. For example, SELECT * FROM db1.table1 will execute regardless of the default database set. However, leaving off the database name will cause the mysql client to use the default database. The following shows two commands to create and change the focus of the database:

mysql> CREATE DATABASE greenhouse;
mysql> USE greenhouse;

Tip

If you want to see all the databases on the server, use the SHOW DATABASES command.

Creating a table requires the, yes, CREATE TABLE command. This command has many options allowing you to specify not only the columns and their data types but also additional options such as indexes, foreign keys, and so on. An index also can be created using the CREATE INDEX command (see the following code). The following code shows how to create a simple table for storing plant sensor data such as what may be used for monitoring a personal greenhouse.4

CREATE TABLE `greenhouse`.`plants` (
  `plant_name` char(30) NOT NULL,
  `sensor_value` float DEFAULT NULL,
  `sensor_event` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `sensor_level` char(5) DEFAULT NULL,
  PRIMARY KEY `plant_name` (`plant_name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Note here that I specified the table name (plants) and four columns (plant_name, sensor_value, sensor_event, and sensor_level). I used several data types. For plant_name, I used a character field with a maximum of 30 characters, a floating-point data type for sensor_value, a timestamp value for sensor_event, and another character field for sensor_level of five characters.

The TIMESTAMP data type is of particular use any time you want to record the date and time of an event or action. For example, it is often helpful to know when a sensor value is read. By adding a TIMESTAMP column to the table, you do not need to calculate, read, or otherwise format a date and time at the sensor or even aggregate node.

Note also that I specified that the plant_name column be defined as a key, which creates an index. In this case, it is also the primary key. The PRIMARY KEY phrase tells the server to ensure that there exists one and only one row in the table that matches the value of the column. You can specify several columns to be used in the primary key by repeating the keyword. Note that all primary key columns must not permit nulls (NOT NULL).

If you cannot determine a set of columns that uniquely identify a row (and you want such a behavior—some favor tables without this restriction, but a good DBA will not), you can use an artificial data type option for integer fields called AUTO INCREMENT . When used on a column (this must be the first column), the server automatically increases this value for each row inserted. In this way, it creates a default primary key. For more information about auto increment columns, see the online MySQL reference manual.

Tip

Best practices suggest using a primary key on a character field to be suboptimal in some situations such as tables with large values for each column or many unique values. This can make searching and indexing slower. In this case, you could use an auto increment field to artificially add a primary key that is smaller in size (but somewhat more cryptic).

There are far more data types available than those shown in the previous example. You should review the online MySQL reference manual for a complete list of data types. See the section “Data Types.” If you want to know the layout or “schema” of a table, use the SHOW CREATE TABLE command.

Tip

Like databases, you can also get a list of all the tables in the database with the SHOW TABLES command.

Searching for Data

The most used basic command you need to know is the command to return the data from the table (also called a result set or rows). To do this, you use the SELECT statement. This SQL statement is the workhorse for a database system. All queries for data will be executed with this command. As such, we will spend a bit more time looking at the various clauses (parts) that can be used starting with the column list.

Note

Although we examine SELECT statements first, if you want to try these out on your system, be sure to run the INSERT statements first.

The SELECT statement allows you to specify which columns you want to choose from the data. The list appears as the first part of the statement. The second part is the FROM clause, which specifies the table(s) you want to retrieve rows from.

Note

The FROM clause can be used to join tables with the JOIN operator.

The order that you specify the columns determines the order shown in the result set. If you want all of the columns, use an asterisks (*) instead. Listing 2-3 demonstrates three statements that generate the same result sets. That is, the same rows will be displayed in the output of each. In fact, I am using a table with only four rows for simplicity.

mysql> SELECT plant_name, sensor_value, sensor_event, sensor_level FROM greenhouse.plants;
+------------------------+--------------+---------------------+--------------+
| plant_name             | sensor_value | sensor_event        | sensor_level |
+------------------------+--------------+---------------------+--------------+
| fern in den            |       0.2319 | 2015-09-23 21:04:35 | NULL         |
| fern on deck           |         0.43 | 2015-09-23 21:11:45 | NULL         |
| flowers in bedroom1    |        0.301 | 2015-09-23 21:11:45 | NULL         |
| weird plant in kitchen |        0.677 | 2015-09-23 21:11:45 | NULL         |
+------------------------+--------------+---------------------+--------------+
4 rows in set (0.00 sec)
mysql> SELECT * FROM greenhouse.plants;
+------------------------+--------------+---------------------+--------------+
| plant_name             | sensor_value | sensor_event        | sensor_level |
+------------------------+--------------+---------------------+--------------+
| fern in den            |       0.2319 | 2015-09-23 21:04:35 | NULL         |
| fern on deck           |         0.43 | 2015-09-23 21:11:45 | NULL         |
| flowers in bedroom1    |        0.301 | 2015-09-23 21:11:45 | NULL         |
| weird plant in kitchen |        0.677 | 2015-09-23 21:11:45 | NULL         |
+------------------------+--------------+---------------------+--------------+
4 rows in set (0.00 sec)
mysql> SELECT sensor_value, plant_name, sensor_level, sensor_event FROM greenhouse.plants;
+--------------+------------------------+--------------+---------------------+
| sensor_value | plant_name             | sensor_level | sensor_event        |
+--------------+------------------------+--------------+---------------------+
|       0.2319 | fern in den            | NULL         | 2015-09-23 21:04:35 |
|         0.43 | fern on deck           | NULL         | 2015-09-23 21:11:45 |
|        0.301 | flowers in bedroom1    | NULL         | 2015-09-23 21:11:45 |
|        0.677 | weird plant in kitchen | NULL         | 2015-09-23 21:11:45 |
+--------------+------------------------+--------------+---------------------+
4 rows in set (0.00 sec)
Listing 2-3

Example SELECT Statements

Note that the first two statements result in the same rows as well as the same columns in the same order. However, the third statement although it generates the same rows, displays the columns in a different order.

You also can use functions in the column list to perform calculations and similar operations. One special example is using the COUNT() function to determine the number of rows in the result set, as shown here. See the online MySQL reference manual for more examples of functions supplied by MySQL.

SELECT COUNT(*) FROM greenhouse.plants;

The next clause in the SELECT statement is the WHERE clause. This is where you specify the conditions you want to use to restrict the number of rows in the result set. That is, only those rows that match the conditions. The conditions are based on the columns and can be quite complex. That is, you can specify conditions based on calculations, results from a join, and more. But most conditions will be simple equalities or inequalities on one or more columns to answer a question. For example, suppose you wanted to see the plants where the sensor value read is less than 0.40? In this case, we issue the following query and receive the results. Note that I specified only two columns: the plant name and the value read from sensor.

mysql> SELECT plant_name, sensor_value FROM greenhouse.plants WHERE sensor_value < 0.40;
+---------------------+--------------+
| plant_name          | sensor_value |
+---------------------+--------------+
| fern in den         |       0.2319 |
| flowers in bedroom1 |        0.301 |
+---------------------+--------------+
2 rows in set (0.01 sec)

There are additional clauses you can use including the GROUP BY clause, which is used for grouping rows for aggregation or counting, and the ORDER BY clause, which is used to order the result set. Let’s take a quick look at each starting with aggregation.

Suppose you wanted to average the sensor values read in the table for each sensor. In this case, we have a table that contains sensor readings over time for a variety of sensors. Although the example contains only four rows (and thus may not be statistically informative), the example demonstrates the concept of aggregation quite plainly, as shown in Listing 2-4. Note that what we receive is simply the average of the four sensor values read.

mysql> SELECT plant_name, sensor_value FROM greenhouse.plants WHERE plant_name = 'fern on deck';
+--------------+--------------+
| plant_name   | sensor_value |
+--------------+--------------+
| fern on deck |         0.43 |
| fern on deck |         0.51 |
| fern on deck |        0.477 |
| fern on deck |         0.73 |
+--------------+--------------+
4 rows in set (0.00 sec)
mysql> SELECT plant_name, AVG(sensor_value) AS avg_value FROM greenhouse.plants WHERE plant_name = 'fern on deck' GROUP BY plant_name;
+--------------+-------------------+
| plant_name   | avg_value         |
+--------------+-------------------+
| fern on deck | 0.536750003695488 |
+--------------+-------------------+
1 row in set (0.00 sec)
Listing 2-4

GROUP BY Example

Note that I specified the average function, AVG(), in the column list and passed in the name of the column I wanted to average. There are many such functions available in MySQL to perform some powerful calculations. Clearly, this is another example of how much power exists in the database server that would require many more resources on a typical lightweight sensor or aggregator node in the network.

Also note that I renamed the column with the average using the AS keyword. You can use this to rename any column specified, which changes the name in the result set, as you can see in the listing.

Another use of the GROUP BY clause is counting. In this case, we replaced AVG() with COUNT() and received the number of rows matching the WHERE clause. More specific, we want to know how many sensor values were stored for each plant.

mysql> SELECT plant_name, COUNT(sensor_value) as num_values FROM greenhouse.plants GROUP BY plant_name;
+------------------------+------------+
| plant_name             | num_values |
+------------------------+------------+
| fern in den            |          1 |
| fern on deck           |          4 |
| flowers in bedroom1    |          1 |
| weird plant in kitchen |          1 |
+------------------------+------------+
4 rows in set (0.00 sec)

Now let’s say we want to see the results of our result set ordered by sensor value. We use the same query that selected the rows for the fern on the deck, but we order the rows by sensor value in ascending and descending order using the ORDER BY clause. Listing 2-5 shows the results of each option.

mysql> SELECT plant_name, sensor_value FROM greenhouse.plants WHERE plant_name = 'fern on deck' ORDER BY sensor_value ASC;
+--------------+--------------+
| plant_name   | sensor_value |
+--------------+--------------+
| fern on deck |         0.43 |
| fern on deck |        0.477 |
| fern on deck |         0.51 |
| fern on deck |         0.73 |
+--------------+--------------+
4 rows in set (0.00 sec)
mysql> SELECT plant_name, sensor_value FROM greenhouse.plants WHERE plant_name = 'fern on deck' ORDER BY sensor_value DESC;
+--------------+--------------+
| plant_name   | sensor_value |
+--------------+--------------+
| fern on deck |         0.73 |
| fern on deck |         0.51 |
| fern on deck |        0.477 |
| fern on deck |         0.43 |
+--------------+--------------+
4 rows in set (0.00 sec)
Listing 2-5

ORDER BY Examples

As I mentioned, there is a lot more to the SELECT statement than shown here, but what we have seen will get you very far, especially when working with data typical of most small- to medium-sized database solutions.

Creating Data

Now that you have a database and tables created, you will want to load or insert data into the tables. You can do so using the INSERT INTO statement. Here we specify the table and the data for the row. The following shows a simple example:

INSERT INTO greenhouse.plants (plant_name, sensor_value) VALUES ('fern in den', 0.2319);

In this example, I am inserting data for one of my plants by specifying the name and value. What about the other columns, you wonder? In this case, the other columns include a timestamp column, which will be filled in by the database server. All other columns (just the one) will be set to NULL, which means no value is available, the value is missing, the value is not zero, or the value is empty.

Note that I specified the columns before the data for the row. This is necessary whenever you want to insert data for fewer columns than what the table contains. To be more specific, leaving the column list off means you must supply data (or NULL) for all columns in the table. Also, the order of the columns listed can be different from the order they are defined in the table. Leaving the column list off will result in the ordering the column data based on how they appear in the table.

You can also insert several rows using the same command by using a comma separated list of the row values, as shown here:

INSERT INTO greenhouse.plants (plant_name, sensor_value) VALUES ('flowers in bedroom1', 0.301), ('weird plant in kitchen', 0.677), ('fern on deck', 0.430);

Here I’ve inserted several rows with the same command. Note that this is just a shorthand mechanism, and except for automatic commits, no different than issuing separate commands.

Updating Data

There are times when you want to change or update data. You may have a case where you need to change the value of one or more columns, replace the values for several rows, or correct formatting or even scale of numerical data. To update data, we use the UPDATE command. You can update a particular column, update a set of columns, perform calculations on one or more columns, and more.

What may be more likely is you or your users will want to rename an object in your database. For example, suppose we determine the plant on the deck is not actually a fern but was an exotic flowering plant. In this case, we want to change all rows that have a plant name of “fern on deck” to “flowers on deck.” The following command performs the change:

UPDATE greenhouse.plants SET plant_name = 'flowers on deck' WHERE plant_name = 'fern on deck';

Note that the key operator here is the SET operator. This tells the database to assign a new value to the column(s) specified. You can list more than one set operation in the command.

Note I used a WHERE clause here to restrict the UPDATE to a particular set of rows. This is the same WHERE clause as you saw in the SELECT statement, and it does the same thing; it allows you to specify conditions that restrict the rows affected. If you do not use the WHERE clause, the updates will apply to all rows.

Caution

Don’t forget the WHERE clause! Issuing an UPDATE command without a WHERE clause will affect all rows in the table!

Deleting Data

Sometimes you end up with data in a table that needs to be removed. Maybe you used test data and want to get rid of the fake rows. Perhaps you want to compact or purge your tables or you want to eliminate rows that no longer apply. To remove rows, use the DELETE FROM command.

Let’s look at an example. Suppose you have a plant-monitoring solution under development and you’ve discovered that one of your sensors or sensor nodes are reading values that are too low because of a coding, wiring, or calibration error. In this case, we want to remove all rows with a sensor value less than 0.20. The following command does this:

DELETE FROM plants WHERE sensor_value < 0.20;

Caution

Don’t forget the WHERE clause! Issuing a DELETE FROM command without a WHERE clause will permanently delete all rows in the table!

Note that I used a WHERE clause here. That is, a conditional statement to limit the rows acted on. You can use whatever columns or conditions you want; just be sure you have the correct ones! I like to use the same WHERE clause in a SELECT statement first. For example, I would issue the following first to check that I am about to delete the rows I want and only those rows. Note that it is the same WHERE clause.

SELECT * FROM plants WHERE sensor_value < 0.20;

Using Indexes

Tables are created without the use of any ordering; that is, they are unordered. Although it is true MySQL will return the data in the same order each time, there is no implied (or reliable) ordering unless you create an index. The ordering I am referring to here is not what you think when sorting (that’s possible with the ORDER BY clause in the SELECT statement).

Rather, indexes are mappings that the server uses to read the data when queries are executed. For example, if you had no index on a table and wanted to select all rows with a value greater than a certain value for a column, the server will have to read all rows to find all the matches. However, if we added an index on that column, the server would have to read only those rows that match the criteria.

I should note that there are several forms of indexes. What I am referring to here is a clustered index where the value for column in the index is stored in the index, allowing the server to read the index only and not the rows to do the test for the criteria.

To create an index, you can either specify the index in the CREATE TABLE statement or issue a CREATE INDEX command. The following shows a simple example:

CREATE INDEX plant_name ON plants (plant_name);

This command adds an index on the plant_name column. Observe how this affects the table.

CREATE TABLE `plants` (
  `plant_name` char(30) NOT NULL,
  `sensor_value` float DEFAULT NULL,
  `sensor_event` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `sensor_level` char(5) DEFAULT NULL,
  PRIMARY KEY (`plant_name`),
  KEY `plant_name` (`plant_name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

Indexes created like this do not affect the uniqueness of the rows in the table. In other words, make sure that there exists one and only one row that can be accessed by a specific value of a specific column (or columns). What I am referring to is the concept of a primary key (or primary index), which is a special option used in the creation of the table as described earlier.

Views

Views are logical mappings of results of one or more tables. They can be referenced as if they were tables in queries, making them a powerful tool for creating subsets of data to work with. You create a view with CREATE VIEW and give it a name similar to a table. The following shows a simple example where we create a test view to read values from a table. In this case, we limit the size of the view (number of rows), but you could use a wide variety of conditions for your views, including combining data from different tables.

CREATE VIEW test_plants AS SELECT * FROM plants LIMIT 5;

Views are not normally encountered in small- or medium-sized database solutions, but I include them to make you aware of them in case you decide to do additional analysis and want to organize the data into smaller groups for easier reading.

Triggers

Another advanced concept (and associated SQL command) is the use of an event-driven mechanism that is “triggered” when data is changed. That is, you can create a short set of SQL commands (a procedure) that will execute when data is inserted or changed.

There are several events or conditions under which the trigger will execute. You can set up a trigger either before or after an update, insert, or delete action. A trigger is associated with a single table and has as its body a special construct that allows you to act on the rows affected. The following shows a simple example:

DELIMITER //
CREATE TRIGGER set_level BEFORE INSERT ON plants FOR EACH ROW
BEGIN
  IF NEW.sensor_value < 0.40 THEN
    SET NEW.sensor_level = 'LOW';
  ELSEIF NEW.sensor_value < 0.70 THEN
    SET NEW.sensor_level = 'OK';
  ELSE
    SET NEW.sensor_level = 'HIGH';
  END IF;
END //
DELIMITER ;

This trigger will execute before each insert into the table. As you can see in the compound statement (BEGIN . . . END), we set a column called sensor_level to LOW, OK, or HIGH depending on the value of the sensor_value. To see this in action, consider the following command. The FOR EACH ROW syntax allows the trigger to act on all rows in the transaction.

INSERT INTO plants (plant_name, sensor_value) VALUES ('plant1', 0.5544);

Because the value we supplied is less than the middle value (0.70), we expect the trigger to fill in the sensor_level column for us. The following shows this indeed is what happened when the trigger fired:

+------------+--------------+---------------------+--------------+
| plant_name | sensor_value | sensor_event        | sensor_level |
+------------+--------------+---------------------+--------------+
| plant1     |       0.5544 | 2015-09-23 20:00:15 | OK           |
+------------+--------------+---------------------+--------------+
1 row in set (0.00 sec)

This demonstrates an interesting and powerful way you can create derived columns with the power of the database server and save the processing power and code in your applications. I encourage you to consider this and similar powerful concepts for leveraging the power of the database server.

Simple Joins

One of the most powerful concepts of database systems is the ability to make relationships (hence the name relational) among the data. That is, data in one table can reference data in another (or several tables). The most simplistic form of this is called a master-detail relationship in which a row in one table references or is related to one or more rows in another.

A common (and classic) example of a master-detail relationship is from an order-tracking system where we have one table containing the data for an order and another table containing the line items for the order. Thus, we store the order information such as customer number and shipping information once and combine or “join” the tables when we retrieve the order proper.

Let’s look at an example from the sample database named world. You can find this database on the MySQL web site ( http://dev.mysql.com/doc/index-other.html ). Feel free to download it and any other sample database. They all demonstrate various designs of database systems. You also will find it handy to practice querying the data as it contains more than a few, simple rows.

Note

If you want to run the following examples, you need to install the world database as described in the documentation for the example ( http://dev.mysql.com/doc/world-setup/en/world-setup-installation.html ).

Listing 2-6 shows an example of a simple join. There is a lot going on here, so take a moment to examine the parts of the SELECT statement, especially how I specified the JOIN clause. You can ignore the LIMIT option because that simply limits the number of rows in the result set.

mysql> USE world;
mysql> SELECT Name, Continent, Language FROM Country JOIN CountryLanguage ON Country.Code = CountryLanguage.CountryCode LIMIT 10;
+-------------+---------------+------------+
| Name        | Continent     | Language   |
+-------------+---------------+------------+
| Aruba       | North America | Dutch      |
| Aruba       | North America | English    |
| Aruba       | North America | Papiamento |
| Aruba       | North America | Spanish    |
| Afghanistan | Asia          | Balochi    |
| Afghanistan | Asia          | Dari       |
| Afghanistan | Asia          | Pashto     |
| Afghanistan | Asia          | Turkmenia  |
| Afghanistan | Asia          | Uzbek      |
| Angola      | Africa        | Ambo       |
+-------------+---------------+------------+
10 rows in set (0.00 sec)
Listing 2-6

Simple JOIN Example

Here I used a JOIN clause that takes two tables specified such that the first table is joined to the second table using a specific column and its values (the ON specifies the match). What the database server does is read each row from the tables and returns only those rows where the value in the columns specified a match. Any rows in one table that are not in the other are not returned.

Tip

You can retrieve those rows with different joins. See the online MySQL reference manual on inner and outer joins for more details.

Note that I included only a few columns. In this case, I specified the country name and continent from the Country table and the language column from the CountryLanguage table. If the column names were not unique (the same column appears in each table), I would have to specify them by table name such as Country.Name. In fact, it is considered good practice to always qualify the columns in this manner.

There is one interesting anomaly in this example that I feel important to point out. In fact, some would consider it a design flaw. Note in the JOIN clause that I specified the table and column for each table. This is normal and correct, but note that the column name does not match in both tables. Although this really doesn’t matter, and creates only a bit of extra typing, some DBAs would consider this erroneous and would have a desire to make the common column name the same in both tables.

Another use for a join is to retrieve common, archival, or lookup data. For example, suppose you had a table that stored details about things that do not change (or rarely change) such as cities associated with ZIP codes or names associated with identification numbers (e.g., SSN). You could store this information in a separate table and join the data on a common column (and values) whenever you needed. In this case, that common column can be used as a foreign key, which is another advanced concept.

Foreign keys are used to maintain data integrity (i.e., if you have data in one table that relates to another table but the relationship needs to be consistent). For example, if you wanted to make sure when you delete the master row that all of the detail rows are also deleted, you could declare a foreign key in the master table to a column (or columns) to the detail table. See the online MySQL reference manual for more information about foreign keys.

This discussion on joins touches only the very basics. Indeed, joins are arguably one of the most difficult and often confused areas in database systems. If you find you want to use joins to combine several tables or extend data so that the data is provided from several tables (outer joins), you should spend some time with an in-depth study of database concepts such as Clare Churcher’s book Beginning Database Design (Apress, 2012).

Stored Routines

There are many more concepts and commands available in MySQL, but two that may be of interest are PROCEDURE and FUNCTION, sometimes called stored routines . I introduce these concepts here so that if you want to explore them, you understand how they are used at a high level.

Suppose you need to run several commands to change data. That is, you need to do some complex changes based on calculations. For these types of operations, MySQL provides the concept of a stored procedure. The stored procedure allows you to execute a compound statement (a series of SQL commands) whenever the procedure is called. Stored procedures are sometimes considered an advanced technique used mainly for periodic maintenance, but they can be handy in even the more simplistic situations.

For example, suppose you want to develop your own database application that uses SQL, but because you are developing it, you need to periodically start over and want to clear out all the data first. If you had only one table, a stored procedure would not help much, but suppose you have several tables spread over several databases (not unusual for larger databases). In this case, a stored procedure may be helpful.

Tip

When entering commands with compound statements in the MySQL client, you need to change the delimiter (the semicolon) temporarily so that the semicolon at the end of the line does not terminate the command entry. For example, use DELIMITER // before writing the command with a compound statement, use // to end the command, and change the delimiter back with DELIMITER ;. This is only when using the client.

Because stored procedures can be quite complicated, if you decide to use them, read the “CREATE PROCEDURE and CREATE FUNCTION Syntax” section of the online MySQL reference manual before trying to develop your own. There is more to creating stored procedures than described in this section.

Now suppose you want to execute a compound statement and return a result—you want to use it as a function. You can use functions to fill in data by performing calculations, data transformation, or simple translations. Functions therefore can be used to provide values to populate column values, provide aggregation, provide date operations, and more.

You have already seen a couple of functions (COUNT, AVG). These are considered built-in functions, and there is an entire section devoted to them in the online MySQL reference manual. However, you also can create your own functions. For example, you may want to create a function to perform data normalization on your data. More specific, suppose you have a sensor that produces a value in a specific range, but depending on that value and another value from a different sensor or lookup table, you want to add, subtract, average, and so on the value to correct it. You could write a function to do this and call it a trigger to populate the value for a calculation column.

Tip

Use a new column for calculated values so that you preserve the original value.

What About Changing Objects?

You may wonder what you to do when you need to modify a table, procedure, trigger, and so on. Rest easy, you do not have to start over from scratch! MySQL provides an ALTER command for each object. That is, there is an ALTER TABLE, ALTER PROCEDURE, and so on. See the online MySQL reference manual section, “Data Definition Statements” for more information about each ALTER command.

Summary

The MySQL database server is a powerful tool. Given its unique placement in the market as the database server for the Internet, it is not surprising that web developers (as well as many startup and similar Internet properties) have chosen MySQL for their solutions. Not only is the server robust and easy to use, it is also available as a free community license that you can use to keep your initial investment within budget.

In this chapter, you discovered some of the power of using the MySQL database server in its traditional role using the SQL interface; how to issue commands for creating databases and tables for storing data as well as commands for retrieving that data. Although this chapter presents only a small primer on MySQL, you learned how to get started with your own installation of MySQL.

In Chapter 3, we look at the NoSQL interface for MySQL. In particular, we look at using MySQL as a document store.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.84.157