Using the mysql Client Program - MySQL Cookbook (2007)

MySQL Cookbook (2007)

Chapter 1. Using the mysql Client Program

Introduction

The MySQL database system uses a client-server architecture that centers around the server , mysqld. The server is the program that actually manipulates databases. Client programs don’t do that directly. Instead, they communicate your intent to the server by means of statements written inStructured Query Language (SQL). Client programs are installed locally on the machine from which you want to access MySQL, but the server can be installed anywhere, as long as clients can connect to it. MySQL is an inherently networked database system, so clients can communicate with a server that is running locally on your machine or one that is running somewhere else, perhaps on a machine on the other side of the planet. Clients can be written for many different purposes, but each interacts with the server by connecting to it, sending SQL statements to it to have database operations performed, and receiving the statement results from it.

One such client is the mysql program that is included in MySQL distributions. When used interactively, mysql prompts you for a statement, sends it to the MySQL server for execution, and then displays the results. This capability makes mysql useful in its own right, but it’s also a valuable tool to help you with your MySQL programming activities. It’s often convenient to be able to quickly review the structure of a table that you’re accessing from within a script, to try a statement before using it in a program to make sure that it produces the right kind of output, and so forth.mysql is just right for these jobs. mysql also can be used noninteractively; for example, to read statements from a file or from other programs. This enables you to use mysql from within scripts or cron jobs or in conjunction with other applications.

This chapter describes mysql’s capabilities so that you can use it more effectively:

§ Starting and stopping mysql

§ Specifying connection parameters and using option files

§ Setting your PATH variable so that your command interpreter can find mysql (and other MySQL programs)

§ Issuing SQL statements interactively and using batch files

§ Canceling and editing statements

§ Controlling mysql output format

To use the examples shown in this book, you’ll need a MySQL user account and a database to work with. The first two sections of the chapter describe how to use mysql to set these up. For demonstration purposes, the examples assume that you’ll use MySQL as follows:

§ The MySQL server is running on the local host

§ Your MySQL username and password are cbuser and cbpass

§ Your database is named cookbook

For your own experimentation, you can violate any of these assumptions. Your server need not be running locally, and you need not use the username , password, or database name that are used in this book. Naturally, if you use different default values on your system, you’ll need to change the examples accordingly.

Even if you do not use cookbook as the name of your database, I recommend that you create a database to be dedicated specifically to trying the examples shown here, rather than trying them with a database that you’re using currently for other purposes. Otherwise, the names of your existing tables may conflict with those used in the examples, and you’ll have to make modifications to the examples that are unnecessary when you use a separate database.

If you have another favorite client program to use for issuing queries, some of the concepts covered in this chapter may not apply. For example, you might prefer the graphical MySQL Query Browser program, which provides a point-and-click interface to MySQL databases. In this case, some of the principles will be different, such as the way that you terminate SQL statements. In mysql, you terminate statements with semicolon (;) characters, whereas in MySQL Query Browser there is an Execute button for terminating statements. Another popular interface is phpMyAdmin, which enables you to access MySQL through your web browser.

Scripts that create the tables used in this chapter can be found in the tables directory of the recipes distribution. Other scripts are located in the mysql directory. For information about obtaining the recipes distribution, see Appendix A.

Setting Up a MySQL User Account

Problem

You need to create an account to use for connecting to the MySQL server running on a given host.

Solution

Use the GRANT statement to set up the MySQL user account. Then use the account’s name and password to make connections to the server.

Discussion

Connecting to a MySQL server requires a username and password. You can also specify the name of the host on which the server is running. If you don’t specify connection parameters explicitly, mysql assumes default values. For example, if you specify no hostname, mysql typically assumes that the server is running on the local host.

If someone else has set you up with an account, just use that account to create and use databases. If not, the following example shows how to use the mysql program to connect to the server and issue a GRANT statement that sets up a user account with privileges for accessing a database namedcookbook. In the commands shown, the % represents the prompt displayed by your shell or command interpreter, and mysql> is the prompt displayed by mysql. Text that you type is shown in bold. Nonbold text (including the prompts) is program output; you do not type it. The arguments tomysql include -h localhost to connect to the MySQL server running on the local host, -p to tell mysql to prompt for a password, and -u root to connect as the MySQL root user.

%mysql -h localhost -p -u root

Enter password: ******

mysql> GRANT ALL ON cookbook.* TO 'cbuser'@'localhost' IDENTIFIED BY 'cbpass';

Query OK, 0 rows affected (0.09 sec)

mysql> QUIT

Bye

If you get a message indicating that mysql cannot be found or that it is a bad command when you enter the mysql command shown on the first line, see What to Do if mysql Cannot Be Found. Otherwise, when mysql prints the password prompt, enter the MySQL root password where you see the ******. (If the MySQL root user has no password, just press the Enter (or Return) key at the password prompt.) Then issue a GRANT statement like the one shown.

To grant the cbuser account access to a database other than cookbook, substitute the database name where you see cookbook in the GRANT statement. To grant access for the cookbook database to an existing account, substitute that account for 'cbuser'@'localhost'. However, in this case, omit the IDENTIFIED BY 'cbpass' part of the statement because otherwise you’ll change the existing account’s current password.

The hostname part of 'cbuser'@'localhost' indicates the host from which you’ll be connecting to the MySQL server when you want to access the cookbook database. To set up an account that will connect to a server running on the local host, use localhost, as shown. If you plan to make connections to the server from another host, substitute that host in the GRANT statement. For example, if you’ll be connecting to the server from a host named xyz.com, the GRANT statement should look like this:

mysql>GRANT ALL ON cookbook.* TO 'cbuser'@'xyz.com' IDENTIFIED BY 'cbpass';

It may have occurred to you that there’s a bit of a paradox involved in the procedure just described. That is, to set up a cbuser account that can make connections to the MySQL server, you must connect to the server first so that you can issue the GRANT statement. I’m assuming that you can already connect as the MySQL root user, because GRANT can be used only by a user such as root that has the administrative privileges needed to set up other user accounts. If you can’t connect to the server as root, ask your MySQL administrator to set up the cbuser account for you.

After the cbuser account has been set up, verify that you can use it to connect to the MySQL server. From the host that was named in the GRANT statement, run the following command to do this (the host named after -h should be the host that is running the MySQL server):

%mysql -h localhost -p -u cbuser

Enter password: cbpass

Now you can proceed to create the cookbook database and tables within it, as described in Creating a Database and a Sample Table. (To make it easier to start mysql without specifying connection parameters each time, you can put them in an option file. See Specifying Connection Parameters Using Option Files.)

MYSQL ACCOUNTS AND LOGIN ACCOUNTS

MySQL accounts are different from login accounts for your operating system. For example, the MySQL root user and the Unix root user are separate and have nothing to do with each other, even though the username is the same in each case. This means they are very likely to have different passwords. It also means you cannot create new MySQL accounts by creating login accounts for your operating system; use the GRANT statement instead.

Creating a Database and a Sample Table

Problem

You want to create a database and set up tables within it.

Solution

Use a CREATE DATABASE statement to create the database, a CREATE TABLE statement for each table that you want to use, and INSERT statements to add rows to the tables.

Discussion

The GRANT statement shown in Setting Up a MySQL User Account sets up privileges for accessing the cookbook database but does not create the database. You need to create it explicitly before you can use it. This section shows how to do that, and also how to create a table and load it with some sample data that can be used for examples in the following sections.

Connect to the MySQL server as shown at the end of Setting Up a MySQL User Account. After you’ve connected successfully, create the database:

mysql>CREATE DATABASE cookbook;

Now you have a database, so you can create tables in it. First, select cookbook as the default database:

mysql>USE cookbook;

Then issue the following statements to create a simple table and populate it with a few rows:[1]

mysql>CREATE TABLE limbs (thing VARCHAR(20), legs INT, arms INT);

mysql> INSERT INTO limbs (thing,legs,arms) VALUES('human',2,2);

mysql> INSERT INTO limbs (thing,legs,arms) VALUES('insect',6,0);

mysql> INSERT INTO limbs (thing,legs,arms) VALUES('squid',0,10);

mysql> INSERT INTO limbs (thing,legs,arms) VALUES('octopus',0,8);

mysql> INSERT INTO limbs (thing,legs,arms) VALUES('fish',0,0);

mysql> INSERT INTO limbs (thing,legs,arms) VALUES('centipede',100,0);

mysql> INSERT INTO limbs (thing,legs,arms) VALUES('table',4,0);

mysql> INSERT INTO limbs (thing,legs,arms) VALUES('armchair',4,2);

mysql> INSERT INTO limbs (thing,legs,arms) VALUES('phonograph',0,1);

mysql> INSERT INTO limbs (thing,legs,arms) VALUES('tripod',3,0);

mysql> INSERT INTO limbs (thing,legs,arms) VALUES('Peg Leg Pete',1,2);

mysql> INSERT INTO limbs (thing,legs,arms) VALUES('space alien',NULL,NULL);

The table is named limbs and contains three columns to record the number of legs and arms possessed by various life forms and objects. The physiology of the alien in the last row is such that the proper values for the arms and legs column cannot be determined; NULL indicates “unknown value.”

Verify that the rows were inserted properly into the table by issuing a SELECT statement:

mysql>SELECT * FROM limbs;

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

| thing | legs | arms |

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

| human | 2 | 2 |

| insect | 6 | 0 |

| squid | 0 | 10 |

| octopus | 0 | 8 |

| fish | 0 | 0 |

| centipede | 100 | 0 |

| table | 4 | 0 |

| armchair | 4 | 2 |

| phonograph | 0 | 1 |

| tripod | 3 | 0 |

| Peg Leg Pete | 1 | 2 |

| space alien | NULL | NULL |

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

At this point, you’re all set up with a database and a table. For general instructions on issuing SQL statements, see Issuing SQL Statements .

NOTE

Statements in this book are shown with SQL keywords such as SELECT or INSERT in uppercase for distinctiveness. However, that’s just a typographical convention. You can enter keywords in any lettercase.


[1] If you don’t want to enter the complete text of the INSERT statements (and I don’t blame you), skip ahead to Repeating and Editing SQL Statements for a shortcut. If you don’t want to type in any of the statements, skip ahead to Telling mysql to Read Statements from a File.

Starting and Stopping mysql

Problem

You want to start and stop the mysql program.

Solution

Invoke mysql from your command prompt to start it, specifying any connection parameters that may be necessary. To leave mysql, use a QUIT statement.

Discussion

To start the mysql program, try just typing its name at your command-line prompt. If mysql starts up correctly, you’ll see a short message, followed by a mysql> prompt that indicates the program is ready to accept statements. To illustrate, here’s what the welcome message looks like (to save space, I won’t show it in any further examples):

%mysql

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 18427 to server version: 5.0.27-log

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql>

If you invoke mysql and you get an error message that it cannot be found or is an invalid command, that means your command interpreter doesn’t know where mysql is installed. See What to Do if mysql Cannot Be Found for instructions on setting the PATH environment variable that your command interpreter uses to find commands.

If mysql tries to start but exits immediately with an “access denied” message, you need to specify connection parameters. The most commonly needed parameters are the host to connect to (the host that runs the MySQL server), your MySQL username, and a password. For example:

%mysql -h localhost -p -u cbuser

Enter password: cbpass

If you don’t have a MySQL username and password, you must obtain permission to use the MySQL server, as described earlier in Setting Up a MySQL User Account.

The way you specify connection parameters for mysql also applies to other MySQL programs such as mysqldump and mysqladmin. For example, to generate a dump file named cookbook.sql that contains a backup of the tables in the cookbook database, execute mysqldump like this:

%mysqldump -h localhost -p -u cbuser cookbook > cookbook.sql

Enter password: cbpass

Some operations require an administrative MySQL account. The mysqladmin program can perform operations that are available only to the MySQL root account, so you need to invoke it as follows:

%mysqladmin -p -u root shutdown

Enter password: ← enter MySQL root account password here

In general, I’ll show commands for MySQL programs in examples with no connection parameter options. I assume that you’ll supply any parameters that you need, either on the command line or in an option file (Specifying Connection Parameters Using Option Files) so that you don’t have to type them each time you invoke mysql, mysqldump, and so forth.

The syntax and default values for the connection parameter options are shown in the following table. These options have both a single-dash short form and a double-dash long form.

Parameter type

Option syntax forms

Default value

Hostname

-h hostname

localhost

--host = hostname

Username

-u username

Your login name

--user = username

Password

-p

None

--password

If the value that you use for an option is the same as its default value, you can omit the option. However, as the table indicates, there is no default password. To supply one, use a -p or --password option, and then enter your password when mysql prompts you for it:

%mysql -p

Enter password: ← enter your password here

If you like, you can specify the password directly on the command line by using -p password (note that there is no space after the -p) or --password = password. I don’t recommend doing this on a multiple-user machine, because the password may be visible to other users who are running tools, such as ps, that report process information.

To terminate a mysql session, issue a QUIT command:

mysql>QUIT

You can also terminate the session by issuing an EXIT command or (under Unix) by typing Ctrl-D.

THE MEANING OF LOCALHOST IN MYSQL

One of the parameters you specify when connecting to a MySQL server is the host on which the server is running. Most programs treat the hostname localhost and the IP address 127.0.0.1 as synonyms for “the local host.” Under Unix, MySQL programs behave differently: by convention, they treat the hostname localhost specially and attempt to connect to the local server using a Unix domain socket file. To force a TCP/IP connection to the local server, use the IP address 127.0.0.1 rather than the hostname localhost. Alternatively, specify a --protocol=tcp option to force use of TCP/IP for connecting.

The default port number is 3306 for TCP/IP connections. The pathname for the Unix domain socket varies, although it’s often /tmp/mysql.sock. To specify the socket file pathname explicitly, use a -S file_name or --socket= file_name option.

Specifying Connection Parameters Using Option Files

Problem

You don’t want to type connection parameters on the command line every time you invoke mysql or other MySQL programs.

Solution

Put the parameters in an option file.

Discussion

To avoid entering connection parameters manually, put them in an option file for mysql to read automatically. Under Unix, your personal option file is named .my.cnf in your home directory. There are also site-wide option files that administrators can use to specify parameters that apply globally to all users. You can use /etc/my.cnf or the my.cnf file in the MySQL installation directory. Under Windows, the option files you can use are the my.ini file in your MySQL installation directory (for example, C:\Program Files\MySQL\MySQL Server 5.0), my.ini in your Windows directory (this is something like C:\WINDOWS or C:\WINNT), or the C:\my.cnf file.

Windows Explorer might hide filename extensions when it displays files, so a file named my.ini or my.cnf may appear to be named just my. Your version of Windows may allow you to disable extension-hiding. Alternatively, issue a DIR command in a console window to see complete filenames.

The following example illustrates the format used to write MySQL option files:

# general client program connection options

[client]

host = localhost

user = cbuser

password = cbpass

# options specific to the mysql program

[mysql]

skip-auto-rehash

pager="/usr/bin/less -E" # specify pager for interactive mode

This format has the following general characteristics:

§ Lines are written in groups (or sections). The first line of a group specifies the group name within square brackets, and the remaining lines specify options associated with the group. The example file just shown has a [client] group and a [mysql] group. Within a group, write option lines in name=value format, where name corresponds to an option name (without leading dashes) and value is the option’s value. If an option doesn’t take any value (such as for the skip-auto-rehash option), list the name by itself with no trailing =value part.

§ In option files, only the long form of an option is allowed. This is in contrast to command lines, where options often can be specified using a short form or a long form. For example, on the command line, the hostname can be given using either -h hostname or --host = hostname. In an option file, only host= hostname is allowed.

§ In option files, spaces are allowed around the = that separates an option name and value. This contrasts with command lines, where no spaces around = are allowed.

§ If an option value contains spaces or other special characters, you can quote it using single or double quotes. The pager option illustrates this.

§ If you don’t need some particular parameter, just leave out the corresponding line. For example, if you normally connect to the default host (localhost), you don’t need any host line. On Unix, if your MySQL username is the same as your operating system login name, you can omit theuser line.

§ It’s common to use an option file to specify options for connection parameters (such as host, user, and password). However, the file can list options that have other purposes. The pager option shown for the [mysql] group specifies the paging program that mysql should use for displaying output in interactive mode. It has nothing to do with how the program connects to the server.

§ The usual option group for specifying client connection parameters is [client]. This group actually is used by all the standard MySQL clients. By listing an option in this group, you make it easier to invoke not just mysql, but also other programs such as mysqldump and mysqladmin.Just make sure that any option you put in this group is understood by all client programs. For example, if you put mysql-specific options such as skip-auto-rehash or pager in the [client] group, that will result in “unknown option” errors for all other programs that use the[client] group, and they won’t run properly.

§ You can define multiple groups in an option file. A common convention is for a program to look for parameters in the [client] group and in the group named for the program itself. This provides a convenient way to list general client parameters that you want all client programs to use, but you can still specify options that apply only to a particular program. The preceding sample option file illustrates this convention for the mysql program, which gets general connection parameters from the [client] group and also picks up the skip-auto-rehash and pager options from the [mysql] group.

§ If a parameter appears multiple times in an option file, the last value found takes precedence. Normally, you should list any program-specific groups following the [client] group so that if there is any overlap in the options set by the two groups, the more general options will be overridden by the program-specific values.

§ Lines beginning with # or ; characters are ignored as comments. Blank lines are ignored, too. # can be used to write comments at the end of option lines, as shown for the pager option.

§ Option files must be plain-text files. If you create an option file with a word processor that uses some nontext format by default, be sure to save the file explicitly as text. Windows users especially should take note of this.

§ Options that specify file or directory pathnames should be written using / as the pathname separator character, even under Windows, which uses \ as the pathname separator. Alternatively, write \ by doubling it as \\ (this is necessary because \ is the MySQL escape character in strings).

If you want to find out which options the mysql program will read from option files, use this command:

%mysql --print-defaults

You can also use the my_print_defaults utility, which takes as arguments the names of the option file groups that it should read. For example, mysql looks in both the [client] and [mysql] groups for options, so you can check which values it will read from option files by using this command:

%my_print_defaults client mysql

Protecting Option Files from Other Users

Problem

Your MySQL username and password are stored in your option file, and you don’t want other users to be able to read that file.

Solution

Set the file’s mode to make it accessible only by you.

Discussion

On a multiple-user operating system such as Unix, you should protect your option file to prevent other users from reading it and finding out how to connect to MySQL using your account. Use chmod to make the file private by setting its mode to enable access only by yourself. Either of the following commands do this:

%chmod 600 .my.cnf

% chmod go-rwx .my.cnf

On Windows, you can use Windows Explorer to set file permissions.

Mixing Command-Line and Option File Parameters

Problem

You’d rather not store your MySQL password in an option file, but you don’t want to enter your username and server host manually.

Solution

Put the username and host in the option file, but not the password. Instead, specify the password interactively when you invoke the mysql program. mysql looks both in the option file and on the command line for connection parameters. If an option is specified in both places, the one on the command line takes precedence.

Discussion

mysql first reads your option file to see what connection parameters are listed there, and then checks the command line for additional parameters. This means you can specify some options one way, and some the other way. For example, you can list your username and hostname in an option file, but use a password option on the command line:

%mysql -p

Enter password: ← enter your password here

Command-line parameters take precedence over parameters found in your option file, so if for some reason you need to override an option file parameter, just specify it on the command line. For example, you might list your regular MySQL username and password in the option file for general-purpose use. If you need to connect on occasion as the MySQL root user, specify the user and password options on the command line to override the option file values:

%mysql -p -u root

Enter password: ← enter MySQL root account password here

To explicitly specify “no password” when there is a nonempty password in the option file, use -p on the command line, and then press Enter when mysql prompts you for the password:

%mysql -p

Enter password: ← press Enter here

What to Do if mysql Cannot Be Found

Problem

When you invoke mysql from the command line, your command interpreter can’t find it.

Solution

Add the directory where mysql is installed to your PATH setting. You’ll then be able to run mysql from any directory easily.

Discussion

If your shell or command interpreter can’t find mysql when you invoke it, you’ll see some sort of error message. It might look like this under Unix:

%mysql

mysql: Command not found.

Or like this under Windows:

C:\>mysql

Bad command or invalid filename

One way to tell your command interpreter where to find mysql is to type its full pathname each time you run it. The command might look like this under Unix:

%/usr/local/mysql/bin/mysql

Or like this under Windows:

C:\>"C:\Program Files\MySQL\MySQL Server 5.0\bin\mysql"

Typing long pathnames gets tiresome pretty quickly. You can avoid the need to do so by changing location into the directory where mysql is installed before you run it. However, I recommend that you not do that. If you do, you’ll be tempted to put all your datafiles and SQL batch files in the same directory as mysql, thus unnecessarily cluttering up what should be a location intended only for programs.

A better solution is to make sure that the directory where mysql is installed is included in the value of the PATH environment variable that lists pathnames of directories where the command interpreter looks for commands. You can then invoke mysql from any directory by entering just its name, and your command interpreter will be able to find it. This eliminates a lot of unnecessary pathname typing.

An additional significant benefit is that because you can easily run mysql from anywhere, you won’t need to put your datafiles in the directory where mysql is located. When you don’t have to run mysql from a particular location, you’re free to organize your files in a way that makes sense to you, not in a way imposed by some artificial necessity. For example, you can create a directory under your home directory for each database you have and put the work files associated with a given database in the appropriate directory.

For instructions on setting your PATH variable, see Appendix B.

I’ve pointed out the importance of the PATH search path variable here because I have seen many questions from people who aren’t aware of the existence of such a thing, and who consequently try to do all their MySQL-related work in the bin directory where mysql is installed. This seems particularly common among Windows users.

On Windows, another way to avoid typing the pathname or changing into the mysql directory is to create a shortcut and place it in a more convenient location such as the desktop. This makes it easy to start mysql just by opening the shortcut. To specify command options or the startup directory, edit the shortcut’s properties. If you don’t always invoke mysql with the same options, it might be useful to create one shortcut for each set of options you need. For example, create one shortcut to connect as an ordinary user for general work and another to connect as the MySQLroot user for administrative purposes.

Issuing SQL Statements

Problem

You’ve started mysql, and now you want to send SQL statements to the MySQL server to be executed.

Solution

Just type them in, but be sure to let mysql know where each one ends.

Discussion

When you invoke mysql, it displays a mysql> prompt to tell you that it’s ready for input. To issue a SQL statement at the mysql> prompt, type it in, add a semicolon (;) at the end to signify the end of the statement, and press Enter. An explicit statement terminator is necessary; mysql doesn’t interpret Enter as a terminator because you can enter a statement using multiple input lines. The semicolon is the most common terminator, but you can also use \g (“go”) as a synonym for the semicolon. Thus, the following examples are equivalent ways of issuing the same statement, even though they are entered differently and terminated differently:

mysql>SELECT NOW();

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

| NOW() |

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

| 2005-11-15 16:18:10 |

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

mysql> SELECT

-> NOW()\g

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

| NOW() |

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

| 2005-11-15 16:18:18 |

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

Notice that for the second statement the prompt changes from mysql> to -> on the second input line. mysql changes the prompt this way to let you know that it’s still waiting to see the statement terminator.

Be sure to understand that neither the ; character nor the \g sequence that serve as statement terminators are part of the statement itself. They’re conventions used by the mysql program, which recognizes these terminators and strips them from the input before sending the statement to the MySQL server. It’s important to remember this when you write your own programs that send statements to the server (as we’ll begin to do in the next chapter). In such programs, you don’t include any terminator characters; the end of the statement string itself signifies the end of the statement. In fact, adding a terminator may well cause the statement to fail with an error.

See Also

mysql also can read statements from a file or from another program. See Recipes and .

Canceling a Partially Entered Statement

Problem

You start to enter a statement, and then decide not to issue it after all.

Solution

Cancel the statement using your line-kill character or the \c sequence.

Discussion

If you change your mind about issuing a statement that you’re entering, cancel it. If the statement is on a single line, backspace over it or use your line-kill character to erase the entire line. (The particular line-kill character to use depends on your terminal setup; for me, and most Unix/Linux users, the character is Ctrl-U; Windows users should press Esc.)

If you’ve entered a statement over multiple lines, the line-kill character erases only the last line. To cancel the statement completely, enter \c, and press Enter. This returns you to the mysql> prompt:

mysql>SELECT *

-> FROM limbs

-> ORDER BY\c

mysql>

Sometimes \c appears to do nothing (that is, the mysql> prompt does not reappear), which leads to the sense that you’re “trapped” in a statement and can’t escape. If \c is ineffective, the cause usually is that you began typing a quoted string and haven’t yet entered the matching end quote that terminates the string. Let mysql’s prompt help you figure out what to do here:

§ If the prompt has changed from mysql> to ">, That means mysql is looking for a terminating double quote. If the prompt is '> or `> instead, mysql is looking for a terminating single quote or backtick. Type the appropriate matching quote to end the string, and then type \c followed by Enter.

§ If the prompt is /*>, you’re in the middle of typing a C-style /* ... */ comment. End the comment by typing */, and then type \c followed by Enter.

Repeating and Editing SQL Statements

Problem

The statement you just entered contains an error, and you want to fix it without typing the whole thing again. Or you want to repeat an earlier statement without retyping it.

Solution

Use mysql’s built-in input-line editing capabilities.

Discussion

If you issue a long statement only to find that it contains a syntax error, what should you do? Type in the entire corrected statement from scratch? No need: mysql maintains a statement history and supports input-line editing. This enables you to recall statements so that you can modify and reissue them easily.

There are many, many editing functions, but most people tend to use a small set of commands for the majority of their editing. A basic set of useful commands is shown in the following table. Typically, you use Up Arrow to recall the previous line, Left Arrow and Right Arrow to move around within the line, and Backspace or Delete to erase characters. To add new characters to the line, just move the cursor to the appropriate spot, and type them in. When you’re done editing, press Enter to issue the statement (the cursor need not be at the end of the line when you do this).

Editing key

Effect of key

Up Arrow

Scroll up through statement history

Down Arrow

Scroll down through statement history

Left Arrow

Move left within line

Right Arrow

Move right within line

Ctrl-A

Move to beginning of line

Ctrl-E

Move to end of line

Backspace

Delete previous character

Ctrl-D

Delete character under cursor

On Windows, the arrow key and Backspace editing functions are available as described in the table, Home and End take the place of Ctrl-A and Ctrl-E, and pressing F7 gives you a menu of recent commands.

Input-line editing is useful for more than just fixing mistakes. You can use it to try variant forms of a statement without retyping the entire thing each time. It’s also handy for entering a series of similar statements. For example, if you want to use the statement history to issue the series ofINSERT statements shown earlier in Creating a Database and a Sample Table to create the limbs table, first enter the initial INSERT statement. Then, to issue each successive statement, press the Up Arrow key to recall the previous statement with the cursor at the end, backspace back through the column values to erase them, enter the new values, and press Enter.

The input-line editing capabilities in mysql are based on the GNU Readline library. You can read its documentation to find out more about the many editing functions that are available. Readline documentation is part of the bash manual, which is available online athttp://www.gnu.org/manual/.

Using Auto-Completion for Database and Table Names

Problem

You wish there was a way to type database and table names more quickly.

Solution

There is: use mysql’s name auto-completion facility.

Discussion

Normally, when you use mysql interactively, it reads the list of database names and the names of the tables and columns in your default (current) database when it starts up. mysql remembers this information to provide name-completion capabilities that are useful for entering statements with fewer keystrokes:

1. Type in a partial database, table, or column name, and then hit the Tab key.

2. If the partial name is unique, mysql completes it for you. Otherwise, you can hit Tab again to see the possible matches.

3. Enter additional characters, and hit Tab again once to complete it or twice to see the new set of matches.

mysql’s name auto-completion capability is based on the table names in the default database, and thus is not available within a mysql session until you select a database, either on the command line or with a USE statement.

Auto-completion enables you to cut down the amount of typing you do. However, if you don’t use this feature, reading name-completion information from the MySQL server may be counterproductive because it can cause mysql to start more slowly when you have a lot of tables in your database. To tell mysql not to read this information so that it starts up more quickly, specify the -A (or --skip-auto-rehash) option on the mysql command line. Alternatively, put a skip-auto-rehash line in the [mysql] group of your MySQL option file:

[mysql]

skip-auto-rehash

To force mysql to read name completion information even if it was invoked in no-completion mode, issue a REHASH or \# command at the mysql> prompt.

Telling mysql to Read Statements from a File

Problem

You want mysql to read statements stored in a file so that you don’t have to enter them manually.

Solution

Redirect mysql’s input, or use the SOURCE command.

Discussion

By default, the mysql program reads input interactively from the terminal, but you can feed it statements in batch mode using other input sources such as a file, another program, or the command arguments. You can also use copy and paste as a source of statement input. This section discusses how to read statements from a file. The next few sections discuss how to take input from other sources.

To create an SQL script for mysql to execute in batch mode, put your statements in a text file. Then invoke mysql, and redirect its input to read from that file:

%mysql cookbook <

filename

Statements that are read from an input file substitute for what you’d normally type in by hand, so they must be terminated with semicolons (or \g), just as if you were entering them manually. One difference between interactive and batch modes is the default output style. For interactive mode, the default is tabular (boxed) format. For batch mode, the default is to delimit column values with tabs. However, you can select whichever output style you want using the appropriate command option. See Selecting Tabular or Tab-Delimited Query Output Format.

Batch mode is convenient when you need to issue a given set of statements on multiple occasions because you need not enter them manually each time. For example, batch mode makes it easy to set up cron jobs that run with no user intervention. SQL scripts also are useful for distributing statements to other people. That is, in fact, how SQL examples from this book are distributed. Many of the examples shown here can be run using script files that are available in the accompanying recipes source distribution. (See Appendix A.) You can feed these files to mysql in batch mode to avoid typing statements yourself. For example, when a recipe shows a CREATE TABLE statement that describes what a particular table looks like, you’ll usually find an SQL batch file in the recipes distribution that can be used to create (and perhaps load data into) the table. Recall that Creating a Database and a Sample Table showed the statements for creating and populating the limbs table. Those statements were shown as you would enter them manually, but the recipes distribution includes a limbs.sql file that contains statements to do the same thing. The file looks like this:

DROP TABLE IF EXISTS limbs;

CREATE TABLE limbs

(

thing VARCHAR(20), # what the thing is

legs INT, # number of legs it has

arms INT # number of arms it has

);

INSERT INTO limbs (thing,legs,arms) VALUES('human',2,2);

INSERT INTO limbs (thing,legs,arms) VALUES('insect',6,0);

INSERT INTO limbs (thing,legs,arms) VALUES('squid',0,10);

INSERT INTO limbs (thing,legs,arms) VALUES('octopus',0,8);

INSERT INTO limbs (thing,legs,arms) VALUES('fish',0,0);

INSERT INTO limbs (thing,legs,arms) VALUES('centipede',100,0);

INSERT INTO limbs (thing,legs,arms) VALUES('table',4,0);

INSERT INTO limbs (thing,legs,arms) VALUES('armchair',4,2);

INSERT INTO limbs (thing,legs,arms) VALUES('phonograph',0,1);

INSERT INTO limbs (thing,legs,arms) VALUES('tripod',3,0);

INSERT INTO limbs (thing,legs,arms) VALUES('Peg Leg Pete',1,2);

INSERT INTO limbs (thing,legs,arms) VALUES('space alien',NULL,NULL);

To execute the statements in this SQL script file in batch mode, change location into the tables directory of the recipes distribution that contains the table-creation scripts, and then run this command:

%mysql cookbook < limbs.sql

You’ll note that the script contains a statement to drop the table if it exists before creating the table anew and loading it with data. That enables you to experiment with the table without worrying about changing its contents because you can restore the table to its baseline state any time by running the script again.

The command just shown illustrates how to specify an input file for mysql on the command line. Alternatively, you can read a file of SQL statements from within a mysql session using a SOURCE filename command (or \. filename, which is synonymous). Suppose that the SQL script filetest.sql contains the following statements:

SELECT NOW();

SELECT COUNT(*) FROM limbs;

You can execute that file from within mysql as follows:

mysql>SOURCE test.sql;

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

| NOW() |

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

| 2006-07-04 10:35:08 |

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

1 row in set (0.00 sec)

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

| COUNT(*) |

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

| 12 |

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

1 row in set (0.01 sec)

SQL scripts can themselves include SOURCE or \. commands to include other scripts. This gives you additional flexibility but also raises the danger that it’s possible to create a source loop. Normally, you should take care to avoid such loops. If you’re feeling mischievous and want to create a loop deliberately to find out how deep mysql can nest input files, here’s how to do it. First, issue the following two statements manually to create a counter table to keep track of the source file depth and initialize the nesting level to zero:

mysql>CREATE TABLE counter (depth INT);

mysql> INSERT INTO counter SET depth = 0;

Then create a script file loop.sql that contains the following lines (be sure each line ends with a semicolon):

UPDATE counter SET depth = depth + 1;

SELECT depth FROM counter;

SOURCE loop.sql;

Finally, invoke mysql, and issue a SOURCE command to read the script file:

%mysql cookbook

mysql> SOURCE loop.sql;

The first two statements in loop.sql increment the nesting counter and display the current depth value. In the third statement, loop.sql sources itself, thus creating an input loop. You’ll see the output whiz by, with the counter display incrementing each time through the loop. Eventually mysqlwill run out of file descriptors and stop with an error:

ERROR:

Failed to open file 'loop.sql', error: 24

What is error 24? Find out by using MySQL’s perror (print error) utility:

%perror 24

OS error code 24: Too many open files

In other words, you have hit the limit imposed by the operating system on the number of open files you can have.

Telling mysql to Read Statements from Other Programs

Problem

You want to shove the output from another program into mysql.

Solution

Use a pipe .

Discussion

Telling mysql to Read Statements from a File used the following command to show how mysql can read SQL statements from a file:

%mysql cookbook < limbs.sql

mysql can also read a pipe, which means that it can receive output from other programs as its input. As a trivial example, the preceding command is equivalent to this one:

%cat limbs.sql | mysql cookbook

Before you tell me that I’ve qualified for this week’s “useless use of cat award,” [2] allow me to observe that you can substitute other commands for cat. The point is that any command that produces output consisting of semicolon-terminated SQL statements can be used as an input source formysql. This can be useful in many ways. For example, the mysqldump utility generates database backups by writing a set of SQL statements that recreate the database. To process mysqldump output, feed it to mysql. This means you can use the combination of mysqldump and mysql to copy a database over the network to another MySQL server:

%mysqldump cookbook | mysql -h some.other.host.com cookbook

Program-generated SQL also can be useful when you need to populate a table with test data but don’t want to write the INSERT statements by hand. Instead, write a short program that generates the statements, and then send its output to mysql using a pipe:

%generate-test-data | mysql cookbook

See Also

Chapter 10 discusses mysqldump further.


[2] Under Windows, the equivalent would be the “useless use of type award”:

C:\>type limbs.sql | mysql cookbook

Entering an SQL One-Liner

Problem

You want to specify a statement to be executed directly on the mysql command line.

Solution

mysql can read a statement from its argument list.

Discussion

To execute a statement directly from the command line, specify it using the -e (or --execute) option. For example, to find out how many rows are in the limbs table, run this command:

%mysql -e "SELECT COUNT(*) FROM limbs" cookbook

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

| COUNT(*) |

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

| 12 |

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

To execute multiple statements this way, separate them with semicolons:

%mysql -e "SELECT COUNT(*) FROM limbs;SELECT NOW()" cookbook

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

| COUNT(*) |

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

| 12 |

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

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

| NOW() |

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

| 2006-07-04 10:42:22 |

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

By default, results generated by statements that are specified with -e are displayed in tabular format if output goes to the terminal, and in tab-delimited format otherwise. To learn what these different formats are, see Sending Query Output to a File or to a Program. To choose a particular format, see Selecting Tabular or Tab-Delimited Query Output Format.

Using Copy and Paste as a mysql Input Source

Problem

You want to take advantage of your graphical user interface (GUI) to make mysql easier to use.

Solution

Use copy and paste to supply mysql with statements to execute. In this way, you can take advantage of your GUI’s capabilities to augment the terminal interface presented by mysql.

Discussion

Copy and paste is useful in a windowing environment that enables you to run multiple programs at once and transfer information between them. If you have a document containing statements open in a window, you can just copy the statements from there and paste them into the window in which you’re running mysql. This is equivalent to typing the statements yourself, but often quicker. For statements that you issue frequently, keeping them visible in a separate window can be a good way to make sure they’re always at your fingertips.

Preventing Query Output from Scrolling off the Screen

Problem

Query output zooms off the top of your screen before you can see it.

Solution

Tell mysql to display output a page at a time, or run mysql in a window that allows scrollback.

Discussion

If a statement produces many lines of output, normally the lines just scroll right off the top of the screen. To prevent this, tell mysql to present output a page at a time by specifying the --pager option.[3] --pager = program tells mysql to use a specific program as your pager:

%mysql --pager=/usr/bin/less

--pager by itself (with no option value) tells mysql to use your default pager, as specified in your PAGER environment variable:

%mysql --pager

If your PAGER variable isn’t set, you must either define it or use the first form of the command to specify a pager program explicitly. To define PAGER, use the instructions given in Appendix B for setting environment variables.

Within a mysql session, you can turn paging on or off using \P or \n, respectively. \P without an argument enables paging using the program specified in your PAGER variable. \P with an argument enables paging using the argument as the name of the paging program:

mysql>\P

PAGER set to /bin/more

mysql> \P /usr/bin/less

PAGER set to /usr/bin/less

mysql> \n

PAGER set to stdout

Another way to deal with long result sets is to use a terminal program that allows you to scroll back through previous output. Programs such as xterm for the X Window System, Terminal for Mac OS X, or the console window for Windows allow you to set the number of output lines saved in the scrollback buffer. Under Windows, you can set up a console window that allows scrollback by using the following procedure:

1. Locate the Console item in the Control Panel or cmd.exe in the following directory: WINDOWS\system32.

2. Create a shortcut to the item by right-clicking on it and dragging the mouse to where you want to place the shortcut (on the desktop, for example).

3. Right-click on the shortcut, and select the Properties item from the menu that appears.

4. Select the Layout tab in the resulting Properties window.

5. Set the screen buffer height to the number of lines you want to save, and click the OK button.

Now you can launch the shortcut to get a scrollable console window that allows output produced by commands in that window to be retrieved using the scrollbar.


[3] The --pager option is not available under Windows.

Sending Query Output to a File or to a Program

Problem

You want mysql output to go somewhere other than your screen.

Solution

Redirect mysql’s output, or use a pipe .

Discussion

mysql chooses its default output format according to whether you run it interactively or noninteractively. Under interactive use, mysql normally sends its output to the terminal and writes query results using tabular format:

mysql>SELECT * FROM limbs;

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

| thing | legs | arms |

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

| human | 2 | 2 |

| insect | 6 | 0 |

| squid | 0 | 10 |

| octopus | 0 | 8 |

| fish | 0 | 0 |

| centipede | 100 | 0 |

| table | 4 | 0 |

| armchair | 4 | 2 |

| phonograph | 0 | 1 |

| tripod | 3 | 0 |

| Peg Leg Pete | 1 | 2 |

| space alien | NULL | NULL |

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

12 rows in set (0.00 sec)

In noninteractive mode (that is, when either the input or output is redirected), mysql writes output in tab-delimited format:

%echo "SELECT * FROM limbs" | mysql cookbook

thing legs arms

human 2 2

insect 6 0

squid 0 10

octopus 0 8

fish 0 0

centipede 100 0

table 4 0

armchair 4 2

phonograph 0 1

tripod 3 0

Peg Leg Pete 1 2

space alien NULL NULL

However, in either context, you can select any of mysql’s output formats using the appropriate command option. This section describes how to send mysql output somewhere other than the terminal. The next several sections discuss the various mysql output formats and how to select them explicitly according to your needs when the default format isn’t what you want.

To save output from mysql in a file, use your shell’s standard redirection capability:

%mysql cookbook >

outputfile

If you run mysql interactively with the output redirected, you won’t be able to see what you’re typing, so generally in this case you’ll also take statement input from a file (or another program):

%mysql cookbook <

inputfile

>

outputfile

You can also send statement output to another program. For example, if you want to mail query output to someone, you might do so like this:

%mysql cookbook <

inputfile

| mail paul

Note that because mysql runs noninteractively in that context, it produces tab-delimited output, which the mail recipient may find more difficult to read than tabular output. Selecting Tabular or Tab-Delimited Query Output Format shows how to fix this problem.

Selecting Tabular or Tab-Delimited Query Output Format

Problem

mysql produces tabular output when you want tab-delimited output, or vice versa.

Solution

Select the desired format explicitly with the appropriate command option.

Discussion

When you use mysql noninteractively (such as to read statements from a file or to send results into a pipe), it writes output in tab-delimited format by default. Sometimes it’s desirable to produce tabular output instead. (These formats are described in Sending Query Output to a File or to a Program.) For example, if you want to print or mail statement results, tab-delimited output doesn’t look very nice. Use the -t (or --table) option to produce tabular output that is more readable:

%mysql -t cookbook <

inputfile

| lpr

% mysql -t cookbook <

inputfile

| mail paul

The inverse operation is to produce batch (tab-delimited) output in interactive mode. To do this, use -B or --batch.

Specifying Arbitrary Output Column Delimiters

Problem

You want mysql to produce statement output using a delimiter other than tabs.

Solution

mysql itself offers no capability for setting the output delimiter, but you can postprocess mysql output to reformat it.

Discussion

In noninteractive mode, mysql separates output columns by tabs and there is no option for specifying the output delimiter. Under some circumstances, it might be desirable to produce output that uses a different delimiter. Suppose that you want to create an output file for use by a program that expects values to be separated by colon characters (:) rather than tabs. Under Unix, you can convert tabs to arbitrary delimiters by using a utility such as tr or sed. For example, to change tabs to colons, any of the following commands would work (TAB indicates where you type a tab character):[4]

%mysql cookbook <

inputfile

| sed -e "s/

TAB

/:/g" >

outputfile

% mysql cookbook <

inputfile

| tr "

TAB

" ":" >

outputfile

% mysql cookbook <

inputfile

| tr "\011" ":" >

outputfile

sed is more powerful than tr because it understands regular expressions and allows multiple substitutions. This is useful when you want to produce output in something like comma-separated values (CSV) format, which requires three substitutions:

1. Escape any quote characters that appear in the data by doubling them, so that when you use the resulting CSV file, they won’t be interpreted as column delimiters.

2. Change the tabs to commas.

3. Surround column values with quotes.

sed allows all three substitutions to be performed in a single command:

%mysql cookbook <

inputfile

\

| sed -e 's/"/""/g' -e 's/

TAB

/","/g' -e 's/^/"/' -e 's/$/"/' >

outputfile

That’s fairly cryptic, to say the least. You can achieve the same result with other languages that may be easier to read. Here’s a short Perl script that does the same thing as the sed command (it converts tab-delimited input to CSV output), and includes comments to document how it works:

#!/usr/bin/perl -w

# csv.pl - convert tab-delimited input to comma-separated values output

while (<>) # read next input line

{

s/"/""/g; # double any quotes within column values

s/\t/","/g; # put "," between column values

s/^/"/; # add " before the first value

s/$/"/; # add " after the last value

print; # print the result

}

If you name the script csv.pl, you can use it like this:

%mysql cookbook <

inputfile

| csv.pl >

outputfile

If you run the command under a version of Windows that doesn’t know how to associate .pl files with Perl, it might be necessary to invoke Perl explicitly:

C:\>mysql cookbook <

inputfile

| perl csv.pl >

outputfile

tr and sed normally are unavailable under Windows. If you need a cross-platform solution, Perl may be more suitable because it runs under both Unix and Windows. (On Unix systems, Perl usually is preinstalled. On Windows, it is freely available for you to install.)

See Also

An even better way to produce CSV output is to use the Perl Text::CSV_XS module, which was designed for that purpose. This module is discussed in Chapter 10, where it’s used to construct a general-purpose file reformatter.


[4] The syntax for some versions of tr is different; consult your local documentation. Also, some shells use the tab character for special purposes such as filename completion. For such shells, type a literal tab into the command by preceding it with Ctrl-V.

Producing HTML or XML Output

Problem

You’d like to turn a query result into HTML or XML.

Solution

mysql can do that for you. Use mysql -H or mysql-X.

Discussion

mysql generates an HTML table from each query result set if you use the -H (or --html) option. This gives you a quick way to produce sample output for inclusion into a web page that shows what the result of a statement looks like. Here’s an example that shows the difference between tabular format and HTML table output (a few line breaks have been added to the HTML output to make it easier to read):

%mysql -e "SELECT * FROM limbs WHERE legs=0" cookbook

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

| thing | legs | arms |

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

| squid | 0 | 10 |

| octopus | 0 | 8 |

| fish | 0 | 0 |

| phonograph | 0 | 1 |

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

% mysql -H -e "SELECT * FROM limbs WHERE legs=0" cookbook

<TABLE BORDER=1>

<TR><TH>thing</TH><TH>legs</TH><TH>arms</TH></TR>

<TR><TD>squid</TD><TD>0</TD><TD>10</TD></TR>

<TR><TD>octopus</TD><TD>0</TD><TD>8</TD></TR>

<TR><TD>fish</TD><TD>0</TD><TD>0</TD></TR>

<TR><TD>phonograph</TD><TD>0</TD><TD>1</TD></TR>

</TABLE>

The first line of the table contains column headings. If you don’t want a header row, see Suppressing Column Headings in Query Output.

mysql creates an XML document from the result of a statement if you use the -X (or --xml) option:

%mysql -X -e "SELECT * FROM limbs WHERE legs=0" cookbook

<?xml version="1.0"?>

<resultset statement="select * from limbs where legs=0

">

<row>

<field name="thing">squid</field>

<field name="legs">0</field>

<field name="arms">10</field>

</row>

<row>

<field name="thing">octopus</field>

<field name="legs">0</field>

<field name="arms">8</field>

</row>

<row>

<field name="thing">fish</field>

<field name="legs">0</field>

<field name="arms">0</field>

</row>

<row>

<field name="thing">phonograph</field>

<field name="legs">0</field>

<field name="arms">1</field>

</row>

</resultset>

You can also write your own XML generator that directly processes query results into XML. See Exporting Query Results as XML.

The -H, --html -X, and --xml options produce output only for statements that generate a result set. There is no output for statements such as INSERT or UPDATE.

See Also

For information on writing your own programs that generate HTML from query results, see Chapter 17.

Suppressing Column Headings in Query Output

Problem

You don’t want to include column headings in query output.

Solution

Turn headings off with the appropriate command option. Normally, this is --skip-column-names, but you can also use -ss.

Discussion

Tab-delimited format is convenient for generating datafiles that you can import into other programs. However, the first row of output for each query lists the column headings by default, which may not always be what you want. Suppose that you have a program named summarize that produces various descriptive statistics for a column of numbers. If you’re producing output from mysql to be used with this program, you wouldn’t want the header row because it would throw off the results. That is, if you ran a command like this, the output would be inaccurate becausesummarize would count the column heading:

%mysql -e "SELECT arms FROM limbs" cookbook | summarize

To create output that contains only data values, suppress the column header row with the --skip-column-names option:

%mysql --skip-column-names -e "SELECT arms FROM limbs" cookbook

| summarize

You can achieve the same effect as --skip-column-names by specifying the “silent” option (-s or --silent) twice:

%mysql -ss -e "SELECT arms FROM limbs" cookbook | summarize

Making Long Output Lines More Readable

Problem

You have a query that produces long output lines that wrap around and look messy on your screen.

Solution

Use vertical output format.

Discussion

Some statements generate output lines that are so long they take up more than one line on your terminal, which can make query results difficult to read. Here is an example that shows what excessively long query output lines might look like on your screen:

mysql>SHOW FULL COLUMNS FROM limbs;

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

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

| Field | Type | Collation | Null | Key | Default | Extra | Priv

ileges | Comment |

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

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

| thing | varchar(20) | latin1_swedish_ci | YES | | NULL | | sele

ct,insert,update,references | |

| legs | int(11) | NULL | YES | | NULL | | sele

ct,insert,update,references | |

| arms | int(11) | NULL | YES | | NULL | | sele

ct,insert,update,references | |

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

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

To avoid the problem, generate “vertical” output with each column value on a separate line. This is done by terminating a statement with \G rather than with a ; character or with \g. Here’s what the result from the preceding statement looks like when displayed using vertical format:

mysql>SHOW FULL COLUMNS FROM limbs\G

*************************** 1. row ***************************

Field: thing

Type: varchar(20)

Collation: latin1_swedish_ci

Null: YES

Key:

Default: NULL

Extra:

Privileges: select,insert,update,references

Comment:

*************************** 2. row ***************************

Field: legs

Type: int(11)

Collation: NULL

Null: YES

Key:

Default: NULL

Extra:

Privileges: select,insert,update,references

Comment:

*************************** 3. row ***************************

Field: arms

Type: int(11)

Collation: NULL

Null: YES

Key:

Default: NULL

Extra:

Privileges: select,insert,update,references

Comment:

To specify vertical output from the command line, use the -E (or --vertical) option when you invoke mysql. This affects all statements issued during the session, something that can be useful when using mysql to execute a script. (If you write the statements in the SQL script file using the usual semicolon terminator, you can select normal or vertical output from the command line by selective use of -E.)

Controlling mysql’s Verbosity Level

Problem

You want mysql to produce more output. Or less.

Solution

Use the -v or -s options for more or less verbosity.

Discussion

When you run mysql noninteractively, not only does the default output format change, it becomes more terse. For example, mysql doesn’t print row counts or indicate how long statements took to execute. To tell mysql to be more verbose, use -v or --verbose. These options can be specified multiple times for increasing verbosity. Try the following commands to see how the output differs:

%echo "SELECT NOW()" | mysql

% echo "SELECT NOW()" | mysql -v

% echo "SELECT NOW()" | mysql -vv

% echo "SELECT NOW()" | mysql -vvv

The counterparts of -v and --verbose are -s and --silent, which also can be used multiple times for increased effect.

Logging Interactive mysql Sessions

Problem

You want to keep a record of what you did in a mysql session.

Solution

Create a tee file.

Discussion

If you maintain a log of an interactive MySQL session, you can refer back to it later to see what you did and how. Under Unix, you can use the script program to save a log of a terminal session. This works for arbitrary commands, so it works for interactive mysql sessions, too. However,script also adds a carriage return to every line of the transcript, and it includes any backspacing and corrections you make as you’re typing. A method of logging an interactive mysql session that doesn’t add extra messy junk to the logfile (and that works under both Unix and Windows) is to start mysql with a --tee option that specifies the name of the file in which to record the session:[5]

%mysql --tee=tmp.out cookbook

To control session logging from within mysql, use \T and \t to turn tee output on or off, respectively. This is useful if you want to record only certain parts of a session:

mysql>\T tmp.out

Logging to file 'tmp.out'

mysql> \t

Outfile disabled.

A tee file contains the statements that you enter as well as the output from those statements, so it’s a convenient way to keep a complete record of them. It’s useful, for example, when you want to print or mail a session or parts of it, or for capturing statement output to include as an example in a document. It’s also a good way to try statements to make sure that you have the syntax correct before putting them in a script file; you can create the script from the tee file later by editing it to remove everything except those statements you want to keep.

mysql appends session output to the end of the tee file rather than overwriting it. If you want an existing file to contain only the contents of a single session, remove the file first before invoking mysql.


[5] It’s called a “tee” because it’s similar to the Unix tee utility. On Unix, read the tee manual page for more background:

%man tee

Creating mysql Scripts from Previously Executed Statements

Problem

You want to reuse statements that you issued during an earlier mysql session.

Solution

Use a tee file from the earlier session, or look in mysql’s statement history file.

Discussion

One way to create a batch file is to enter your statements into the file from scratch with a text editor and hope that you don’t make any mistakes while typing them. But it’s often easier to use statements that you’ve already verified as correct. How? First, try the statements “by hand” usingmysql in interactive mode to make sure they work properly. Then extract the statements from a record of your session to create the batch file. Two sources of information are particularly useful for creating SQL scripts:

§ You can record all or parts of a mysql session by using the --tee command option or the \T command from within mysql. (See Logging Interactive mysql Sessions.)

§ Under Unix, a second option is to use your history file. mysql maintains a record of your statements, which it stores in the file .mysql_history in your home directory.

A tee file session log has more context because it contains statement input and output both, not just the text of the statements. This additional information can make it easier to locate the parts of the session you want. (Of course, you must also remove the extra stuff to create a batch file from the tee file.) Conversely, the history file is more concise. It contains only the statements you issue, so there are fewer extraneous lines to delete to obtain the statements you want. Choose whichever source of information best suits your needs.

Using User-Defined Variables in SQL Statements

Problem

You want to save a value produced by an expression so that you can refer to it in a subsequent statement.

Solution

Use a user-defined variable to store the value for later use.

Discussion

You can assign a value returned by a SELECT statement to a user-defined variable, and then refer to the variable later in your mysql session. This provides a way to save a result returned from one statement, and then refer to it later in other statements. The syntax for assigning a value to a user variable within a SELECT statement is @ var_name := value, where var_name is the variable name, and value is a value that you’re retrieving. The variable can be used in subsequent statements wherever an expression is allowed, such as in a WHERE clause or in an INSERT statement.

A common situation in which user variables come in handy is when you need to issue successive statements on multiple tables that are related by a common key value. Suppose that you have a customers table with a cust_id column that identifies each customer, and an orders table that also has a cust_id column to indicate which customer each order is associated with. If you have a customer name and you want to delete the customer record as well as all the customer’s orders, you need to determine the proper cust_id value for that customer, and then delete rows from both the customers and orders tables that match the ID. One way to do this is to first save the ID value in a variable, and then refer to the variable in the DELETE statements:

mysql>SELECT @id := cust_id FROM customers WHERE cust_id='

customer name

';

mysql> DELETE FROM orders WHERE cust_id = @id;

mysql> DELETE FROM customers WHERE cust_id = @id;

The preceding SELECT statement assigns a column value to a variable, but variables also can be assigned values from arbitrary expressions. The following statement determines the highest sum of the arms and legs columns in the limbs table and assigns it to the @max_limbs variable:

mysql>SELECT @max_limbs := MAX(arms+legs) FROM limbs;

Another use for a variable is to save the result from LAST_INSERT_ID() after creating a new row in a table that has an AUTO_INCREMENT column:

mysql>SELECT @last_id := LAST_INSERT_ID();

LAST_INSERT_ID() returns the value of the new AUTO_INCREMENT value. By saving it in a variable, you can refer to the value several times in subsequent statements, even if you issue other statements that create their own AUTO_INCREMENT values and thus change the value returned byLAST_INSERT_ID(). This technique is discussed further in Chapter 11.

User variables hold single values. If you assign a value to a variable using a statement that returns multiple rows, the value from the last row is used:

mysql>SELECT @name := thing FROM limbs WHERE legs = 0;

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

| @name := thing |

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

| squid |

| octopus |

| fish |

| phonograph |

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

mysql> SELECT @name;

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

| @name |

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

| phonograph |

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

If the statement returns no rows, no assignment takes place, and the variable retains its previous value. If the variable has not been used previously, that value is NULL:

mysql>SELECT @name2 := thing FROM limbs WHERE legs < 0;

Empty set (0.00 sec)

mysql> SELECT @name2;

+--------+

| @name2 |

+--------+

| NULL |

+--------+

To set a variable explicitly to a particular value, use a SET statement. SET syntax can use either := or = to assign the value:

mysql>SET @sum = 4 + 7;

mysql> SELECT @sum;

+------+

| @sum |

+------+

| 11 |

+------+

SET also can be used to assign a SELECT result to a variable, provided that you write the SELECT as a subquery (that is, within parentheses), and it returns a single value. For example:

mysql>SET @max_limbs = (SELECT MAX(arms+legs) FROM limbs);

A given variable’s value persists until you assign it another value or until the end of your mysql session, whichever comes first.

User variable names are not case-sensitive:

mysql>SET @x = 1, @X = 2; SELECT @x, @X;

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

| @x | @X |

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

| 2 | 2 |

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

NOTE

Before MySQL 5.0, user variable names are case-sensitive.

User variables can appear only where expressions are allowed, not where constants or literal identifiers must be provided. Although it’s tempting to attempt to use variables for such things as table names, it doesn’t work. For example, you might try to generate a temporary table name using a variable as follows, but it won’t work:

mysql>SET @tbl_name = CONCAT('tbl_',FLOOR(RAND()*1000000));

mysql> CREATE TABLE @tbl_name (int_col INT);

ERROR 1064: You have an error in your SQL syntax near '@tbl_name

(int_col INT)'

User variables are a MySQL-specific extension to standard SQL. They will not work with other database engines.

Numbering Query Output Lines

Problem

You’d like the lines of a query result nicely numbered.

Solution

Postprocess the output from mysql or use a user-defined variable.

Discussion

The --skip-column-names option for mysql can be useful in combination with cat -n when you want to number the output rows from a query under Unix:

%mysql --skip-column-names -e "SELECT thing, arms FROM limbs" cookbook | cat -n

1 human 2

2 insect 0

3 squid 10

4 octopus 8

5 fish 0

6 centipede 0

7 table 0

8 armchair 2

9 phonograph 1

10 tripod 0

11 Peg Leg Pete 2

12 NULL

Another option is to use a user variable. Expressions involving variables are evaluated for each row of a query result, a property that you can use to provide a column of row numbers in the output:

mysql>SET @n = 0;

mysql> SELECT @n := @n+1 AS rownum, thing, arms, legs FROM limbs;

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

| rownum | thing | arms | legs |

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

| 1 | human | 2 | 2 |

| 2 | insect | 0 | 6 |

| 3 | squid | 10 | 0 |

| 4 | octopus | 8 | 0 |

| 5 | fish | 0 | 0 |

| 6 | centipede | 0 | 100 |

| 7 | table | 0 | 4 |

| 8 | armchair | 2 | 4 |

| 9 | phonograph | 1 | 0 |

| 10 | tripod | 0 | 3 |

| 11 | Peg Leg Pete | 2 | 1 |

| 12 | space alien | NULL | NULL |

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

Using mysql as a Calculator

Problem

You need a quick way to evaluate an expression.

Solution

Use mysql as a calculator. MySQL doesn’t require every SELECT statement to refer to a table, so you can select the results of arbitrary expressions.

Discussion

SELECT statements typically refer to some table or tables from which you’re retrieving rows. However, in MySQL, SELECT need not reference any table at all, which means that you can use the mysql program as a calculator for evaluating an expression:

mysql>SELECT (17 + 23) / SQRT(64);

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

| (17 + 23) / SQRT(64) |

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

| 5.00000000 |

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

This is also useful for checking how a comparison works. For example, to determine whether a given string comparison is case-sensitive, try a statement such as the following:

mysql>SELECT 'ABC' = 'abc';

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

| 'ABC' = 'abc' |

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

| 1 |

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

The result of this comparison is 1 (meaning “true”; in general, nonzero values are true). Expressions that evaluate to false return zero:

mysql>SELECT 'ABC' = 'abcd';

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

| 'ABC' = 'abcd' |

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

| 0 |

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

User variables can store the results of intermediate calculations. The following statements use variables this way to compute the total cost of a hotel bill:

mysql>SET @daily_room_charge = 100.00;

mysql> SET @num_of_nights = 3;

mysql> SET @tax_percent = 8;

mysql> SET @total_room_charge = @daily_room_charge * @num_of_nights;

mysql> SET @tax = (@total_room_charge * @tax_percent) / 100;

mysql> SET @total = @total_room_charge + @tax;

mysql> SELECT @total;

+--------+

| @total |

+--------+

| 324 |

+--------+

Using mysql in Shell Scripts

Problem

You want to invoke mysql from within a shell script rather than use it interactively.

Solution

There’s no rule against this. Just be sure to supply the appropriate arguments to the command.

Discussion

If you need to process query results within a program, you’ll typically use a MySQL programming interface designed specifically for the language you’re using (for example, in a Perl script, you use the DBI interface; see Recipe 2.1). But for simple, short, or quick-and-dirty tasks, it might be easier just to invoke mysql directly from within a shell script, possibly postprocessing the results with other commands. For example, an easy way to write a MySQL server status tester is to use a shell script that invokes mysql, as is demonstrated in this section. Shell scripts are also useful for prototyping programs that you intend to convert for use with a programming interface later.

For Unix shell scripting, I recommend that you stick to shells in the Bourne shell family, such as sh, bash, or ksh. (The csh and tcsh shells are more suited to interactive use than to scripting.) This section provides some examples showing how to write Unix scripts for /bin/sh, and comments briefly on Windows scripting.

See Appendix B if you need instructions for running programs from your command interpreter or for making sure that your PATH environment variable is set properly to tell your command interpreter which directories to search for installed programs.

The scripts discussed here can be found in the mysql directory of the recipes distribution.

Writing shell scripts under Unix

Here is a shell script that reports the current uptime of the MySQL server. It runs a SHOW STATUS statement to get the value of the Uptime status variable that contains the server uptime in seconds:[6]

#!/bin/sh

# mysql_uptime.sh - report server uptime in seconds

mysql --skip-column-names -B -e "SHOW /*!50002 GLOBAL */ STATUS LIKE 'Uptime'"

The mysql_uptime.sh script runs mysql using --skip-column-names to suppress the column header line, -B to generate batch (tab-delimited) output, and -e to indicate the statement string to execute. The first line of the script that begins with #! is special. It indicates the pathname of the program that should be invoked to execute the rest of the script, /bin/sh in this case. To use the script, create a file named mysql_uptime.sh that contains the preceding lines, make it executable with chmod +x, and run it. The resulting output looks like this:

%./mysql_uptime.sh

Uptime 1260142

The command shown here begins with ./, indicating that the script is located in your current directory. If you move the script to a directory named in your PATH setting, you can invoke it from anywhere, but then you should omit the leading ./ when you run the script.

If you prefer a report that lists the time in days, hours, minutes, and seconds rather than just seconds, you can use the output from the mysql STATUS statement, which provides the following information:

mysql>STATUS;

Connection id: 12347

Current database: cookbook

Current user: cbuser@localhost

Current pager: stdout

Using outfile: ''

Server version: 5.0.27-log

Protocol version: 10

Connection: Localhost via UNIX socket

Server characterset: latin1

Db characterset: latin1

Client characterset: latin1

Conn. characterset: latin1

UNIX socket: /tmp/mysql.sock

Uptime: 14 days 14 hours 2 min 46 sec

For uptime reporting, the only relevant part of that information is the line that begins with Uptime. It’s a simple matter to write a script that sends a STATUS command to the server and filters the output with grep to extract the desired line:

#!/bin/sh

# mysql_uptime2.sh - report server uptime

mysql -e STATUS | grep "^Uptime"

The result looks like this:

%./mysql_uptime2.sh

Uptime: 14 days 14 hours 2 min 46 sec

The preceding two scripts specify the statement to be executed using the -e command option, but you can use other mysql input sources described earlier in the chapter, such as files and pipes. For example, the following mysql_uptime3.sh script is like mysql_uptime2.sh but provides input tomysql using a pipe:

#!/bin/sh

# mysql_uptime3.sh - report server uptime

echo STATUS | mysql | grep "^Uptime"

Some shells support the concept of a “here-document,” which serves essentially the same purpose as file input to a command, except that no explicit filename is involved. (In other words, the document is located “right here” in the script, not stored in an external file.) To provide input to a command using a here-document, use the following syntax:

command <<MARKERinput line 1input line 2input line 3

...

MARKER

<<MARKER signals the beginning of the input and indicates the marker symbol to look for at the end of the input. The symbol that you use for MARKER is relatively arbitrary, but should be some distinctive identifier that does not occur in the input given to the command.

Here-documents are a useful alternative to the -e option when you need to specify a lengthy statement or multiple statements as input. In such cases, when -e becomes awkward to use, a here-document is more convenient and easier to write. Suppose that you have a log table log_tbl that contains a column date_added to indicate when each row was added. A statement to report the number of rows that were added yesterday looks like this:

SELECT COUNT(*) As 'New log entries:'

FROM log_tbl

WHERE date_added = DATE_SUB(CURDATE(),INTERVAL 1 DAY);

That statement could be specified in a script using -e, but the command line would be difficult to read because the statement is so long. A here-document is a more suitable choice in this case because you can write the statement in more readable form:

#!/bin/sh

# new_log_entries.sh - count yesterday's log entries

mysql cookbook <<MYSQL_INPUT

SELECT COUNT(*) As 'New log entries:'

FROM log_tbl

WHERE date_added = DATE_SUB(CURDATE(),INTERVAL 1 DAY);

MYSQL_INPUT

When you use -e or here-documents, you can refer to shell variables within the statement input—although the following example demonstrates that it might be best to avoid the practice. Suppose that you have a simple script count_rows.sh for counting the rows of any table in the cookbookdatabase:

#!/bin/sh

# count_rows.sh - count rows in cookbook database table

# require one argument on the command line

if [ $# -ne 1 ]; then

echo "Usage: count_rows.sh tbl_name";

exit 1;

fi

# use argument ($1) in the query string

mysql cookbook <<MYSQL_INPUT

SELECT COUNT(*) AS 'Rows in table:' FROM $1;

MYSQL_INPUT

The script uses the $# shell variable, which holds the command-line argument count, and $1, which holds the first argument after the script name. count_rows.sh makes sure that exactly one argument was provided, and then uses it as a table name in a row-counting statement. To run the script, invoke it with a table name argument:

%./count_rows.sh limbs

Rows in table:

12

Variable substitution can be helpful for constructing statements, but you should use this capability with caution. If your script can be executed by other users on your system, someone can invoke it with malicious intent as follows:

%./count_rows.sh "limbs;DROP TABLE limbs"

This is a simple form of “SQL injection” attack. After argument substitution, the resulting input to mysql looks like this:

SELECT COUNT(*) AS 'Rows in table:' FROM limbs;DROP TABLE limbs;

This input counts the table rows, and then destroys the table! For this reason, it may be prudent to limit use of variable substitution to your own private scripts. Alternatively, rewrite the script using an API that enables special characters such as ; to be dealt with and rendered harmless.Handling Special Characters and NULL Values in Statements covers techniques for doing this.

Writing shell scripts under Windows

Under Windows, you can run mysql from within a batch file (a file with a .bat extension). Here is a Windows batch file, mysql_uptime.bat, that is similar to the mysql_uptime.sh Unix shell script shown earlier:

@ECHO OFF

REM mysql_uptime.bat - report server uptime in seconds

mysql --skip-column-names -B -e "SHOW /*!50002 GLOBAL */ STATUS LIKE 'Uptime'"

Batch files can be invoked without the .bat extension:

C:\>mysql_uptime

Uptime 9609

Windows scripting has some serious limitations, however. For example, here-documents are not supported, and command argument quoting capabilities are more limited. One way around these problems is to install a more reasonable working environment; see the sidebar “Finding the Windows Command Line Restrictive?”

FINDING THE WINDOWS COMMAND LINE RESTRICTIVE?

If you’re a Unix user who is comfortable with the shells and utilities that are part of the Unix command-line interface, you probably take for granted some of the commands used in this chapter, such as grep, sed, and tr. These tools are so commonly available on Unix systems that it can be a rude and painful shock to realize that they are nowhere to be found if at some point you find it necessary to work at the console prompt under Windows.

One way to make the Windows command-line environment more palatable is to install Cygnus tools for Windows (Cygwin) or Unix for Windows (UWIN). These packages include some of the more popular Unix shells as well as many of the utilities that Unix users have come to expect. Programming tools such as compilers are available with each package as well. The package distributions may be obtained at the following locations:

http://www.research.att.com/sw/tools/uwin/

http://www.cygwin.com/

These distributions can change the way you use this book under Windows, because they eliminate some of the exceptions where I qualify commands as available under Unix but not Windows. By installing Cygwin or UWIN, many of those distinctions become irrelevant.


[6] For an explanation of the /*!50002 GLOBAL */ comment, see Monitoring the MySQL Server.