Cover | Table of Contents | Colophon
http://www.mysql.com/it-resources/benchmarks for
more details). For a database long dismissed by many people, MySQL is
remarkably scalable, and is able to handle tens of thousands of
tables and billions of rows of data. Plus, it manages small amounts
of data quickly and smoothly.http://www.mysql.com/it-resources/benchmarks for
more details). For a database long dismissed by many people, MySQL is
remarkably scalable, and is able to handle tens of thousands of
tables and billions of rows of data. Plus, it manages small amounts
of data quickly and smoothly.mysqld_safe script is the most common way to start
mysqld, because the script can restart the
daemon if it crashes. This helps ensure minimal downtime for database
services. The script mysqld_multi is used to start
multiple sessions of mysqld_safe, and thereby
multiple mysqld instances, for handling requests
from different ports and different Unix socket files, and to make it
easier to serve different sets of databases. For MS Windows NT and
2000 servers, there's mysqld-nt.
It supports the named pipes that some Windows systems use instead of
socket files.http://www.perl.org to download and
install a copy of Perl on non-Windows systems, and
http://www.activestate.com/Products/ActivePerl
to download and install a copy of ActivePerl on Windows systems.http://www.fsf.org/licenses for more details on
the GPL.http://www.mysql.com/company/legal/licensing.http://lists.mysql.com. On
this mailing list page, you will find links for subscribing to each
list. When you click a subscription link, you will see a very simple
form on which to enter your email address. Some subscribers,
incidentally, like to use a special email address and name
representing their online persona. It allows you anonymity and may
make sorting emails easier. Others, however, prefer to use their real
name and contact information. After you enter your email address, you
will receive an automated message to confirm your address. That email
will have a link to the MySQL site with some parameters identifying
your address. Click the link, and it will open your web browser and
confirm your subscription.http://dev.mysql.com/doc. You can read the
material online or download it in a couple of formats (e.g., HTML or
PDF). It is also available in hardcopy format: MySQL
Language Reference and MySQL
Administrator's Guide, both from MySQL
Press.http://www.onlamp.com/onlamp/general/mysql.csp).
Incidentally, I've contributed a few articles to
that publication on MySQL and related topics. I've
also written many articles on MySQL for my column on Unix Review.com
(http://www.unixreview.com/mysql). MySQL AB
also provides some in-depth articles on MySQL. You can find them at
http://dev.mysql.com/downloads)
or from one of its mirror sites (http://dev.mysql.com/downloads/mirrors.html).http://www.gnu.org/).groupadd mysql useradd -g mysql mysql tar xvfz /tmp/mysql-version.tar.gz cd mysql-version
--prefix option with a value set to equal the
desired directory. To set the Unix socket file's
path, you can use --with-unix-socket-path. If you
would like to use a different character set from the default of
latin1, use --with-charset.
Here is an example of how you might configure MySQL with these
particular options before building the binary files:http://www.gnu.org).groupadd mysql
useradd -g mysql mysql
cd /usr/local
tar xvfz /tmp/mysql-version.tar.gzln -s /usr/local/mysql-version /usr/local/mysqlrpm -ivh MySQL-server-version.rpm \ MySQL-client-version.rpm
mysqladmin -u root shutdown
sudo /usr/local/mysql/bin/mysqld_safe [Ctrl-z] bg
http://support.novell.com). You can find the
latest version of LibC at http://developer.novell.com/ndk/libc.htm.
Another requirement for installing MySQL is that the MySQL server and
data be installed on an NSS volume.mysqladmin -u root shutdown
SYS:MYSQL) where MySQL is to be
installed. Unpack the compressed binary package to that location.
When the zip file has finished unpacking, you can establish a search
path for the directory that holds the MySQL NLM's by
entering the following from the server console:SEARCH ADD SYS:MYSQL\BIN
.\scripts\mysql_install_db
mysqld_safe
SEARCH ADD SYS:MYSQL\BIN MYSQLD_SAFE --autoclose --skip-external-locking
mysqld -remove
msyqladmin -u root shutdown
http://www.winzip.com) to uncompress the
files. One of the files is named setup.exe.
Double-click it to start the installer for this package. From this
point, the installation process is pretty much the same for the
packages that use the installer.[mysqld]. Under
this heading you could add something like log =
/var/log/mysql to enable logging and to set the directory
for the log files to the one given. You can list many options in the
file for a particular group. For a complete listing and explanation
of these options, see Chapter 10.mysql -u root -p
PATH=$PATH:/usr/local/mysql/bin export PATH
mysql -h host -u user -p
PATH=$PATH:/usr/local/mysql/bin export PATH
mysql -h host -u user -p
CREATE DATABASE bookstore;
USE bookstore;
CREATE TABLE books ( rec_id INT, title VARCHAR(50), author VARCHAR(50) );
SHOW
DATABASES statement like so:SHOW DATABASES; +-----------+ | Database | +-----------+ | bookstore | | mysql | | test | +-----------+
SHOW
DATABASES statement lists not only the database
that we've created, but also two others. One is the
mysql database, which contains data on user
privileges. This was covered in Chapter 2. The
third one listed is the test database, which is
set up by default when MySQL is installed. It's
there as a convenience for you to be able to add tables or run SQL
statements for testing.USE statement shown earlier, we would enter the
following statement:SHOW TABLES; +---------------------+ | Tables_in_bookstore | +---------------------+ | authors | | books | +---------------------+
SHOWTABLES statement provides
a list containing our two tables, just as we expected. If you want to
see a list of tables from another database while still using the
bookstore database, add a
FROM clause to the previous statement:USE bookstore; SHOW TABLES FROM mysql;
INSERT statement. With INSERT,
we can add one or more records at a time. Before adding information
on a book to our books table, because it refers
to a field in our authors table, we need to add
the author's information to the latter.
We'll do this by entering these SQL statements
through the mysql client:INSERT INTO authors
(author_last, author_first, country)
VALUES('Vernon','Olympia','USA');INSERT INTO books
(title, author_id, isbn, genre, pub_year)
VALUES('Eden', LAST_INSERT_ID( ),'0802117287','novel','2003');INSERT syntax is to name the columns for
which the values are to be inserted, as we're doing
here. If you're going to enter values for all of the
columns, you don't need to name the columns. In the
second SQL statement, we've listed the columns in an
order that's different from their order in the
table. That's acceptable to MySQL; we just have to
be sure that our values are in the same order. We are getting the
author_id number for the row just inserted in
the previous statement by using the LAST_INSERT_ID() function.SELECT statement to select the data that we
want. To get all of the columns and rows from the
books table, enter the following:SELECT * FROM books;
WHERE clause to the end of our
SELECT statement:SELECT rec_id, title, description FROM books WHERE genre = 'novel';
SELECT books.rec_id, title, pub_year,
CONCAT(author_first, ' ', author_last) AS author
FROM books, authors
WHERE author_last = 'Vernon'
AND author_id = authors.rec_id;CONCAT( ). With this function you can take bits of
data and merge them together with text to form more desirable-looking
output. In this case, we're taking the
author's first name and pasting a space (in quotes)
onto the end of it, and then the author's last name
onto the end of that. The results will appear in the output display
as one column, which we've given a column heading of
ORDER BY clause. Suppose that we want a list of
plays written by William Shakespeare from our database. We could
enter the following SQL statement to retrieve such a list and to sort
the data by the play title:SELECT books.rec_id, title, publisher FROM books, authors, publishers WHERE author_last = 'Shakespeare' AND genre = 'play' AND author_id = authors.rec_id AND publisher_id = publishers.rec_id ORDER BY title, pub_year;
ORDER BY
clause comes at the end, after the WHERE clause.
First, we're ordering the data results by the
title column and then, within
title, by the pub_year
column, or the year that the particular printing of the play was
published. By default, data is sorted in ascending alphanumeric
order. If we want to order the results in descending order for the
titles, we can just add a DESC flag immediately
after the title column in the ORDER
BY clause and before the comma that precedes
pub_year.LIMIT clause to
the end of the previous SQL statement like so:SELECT books.rec_id, title FROM books, authors, publishers WHERE author_last = 'Shakespeare' AND genre = 'play' AND author_id = authors.rec_id AND publisher_id = publishers.rec_id ORDER BY title, pub_year LIMIT 20;
ORDER BY clause. If we want to retrieve the
next 10, we would adjust the LIMIT clause to
specify the number of rows to skip, along with the number of records
to retrieve. So, if we want to skip the first 20 rows and list the
next 10 rows from our sort, we would replace the
LIMIT clause in the SQL statement with this one:... LIMIT 20, 10;
SELECT statement containing a COUNT() function like this:SELECT COUNT(*) FROM books, authors WHERE author_last = 'Tolstoy' AND author_id = authors.rec_id; +----------+ | COUNT(*) | +----------+ | 12 | +----------+
SELECT SUM(sale_amount) AS 'Armadillo Sales' FROM orders, books, authors WHERE title = 'Armadillo' AND author_last = 'Boyd' AND book_id = books.rec_id AND author_id = authors.rec_id; +-----------------+ | Armadillo Sales | +-----------------+ | 250.25 | +-----------------+
WHERE clause. Then it adds those numbers and
displays the sum with the column heading given. Most column names
appear in only one table, so MySQL knows what we mean even if we
don't specify the table each column is in; for a
couple of columns we need to use the
table.column format.SELECT purchase_date AS 'Purchase Date' FROM orders WHERE rec_id = '1250'; +---------------+ | Purchase Date | +---------------+ | 2004-03-01 | +---------------+
UPDATE statement. With an
UPDATE statement, you can change data for all rows
or for specific records based on a WHERE clause.
Looking back on the results displayed from an earlier query, we can
see that Olympia Vernon's book
Logic has a copyright year of 2003.
That's not correct; it should read 2004. To change
or update that bit of information, enter the following SQL statement:UPDATE books SET pub_year = '2004' WHERE rec_id = '2'; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0
SET keyword with the column to change
and its corresponding new value. If we want to change the values of
more than one column, we would provide a comma-separated list of each
column along with the equals-sign operator and the new respective
values. SET is declared only once, by the way.WHERE clause in which
we're limiting the rows that will change by
specifying a condition the row must meet. In this case, our condition
is for a specific value of a unique column, so only one row will be
changed. The results of the query show that one row was affected, one
row was matched, one row was changed, and there were no errors to
generate warnings.INSERT,
we'll end up with a duplicate row. To prevent this,
we can use the REPLACE statement, which inserts
new rows and replaces existing rows with new data. From
MySQL's perspective, duplicates occur only when
unique columns would contain the same value. Because the
rec_id column is assigned automatically,
it's unlikely that we would duplicate it, because we
wouldn't tend to assign its value when adding
records. What's unique about each book is its ISBN
number, which is the bar-code number on the back of the book. To
ensure that we do not have rows with the same ISBN number,
we'll alter our DELETE statement. For example, if we want to
delete all rows of data from our books table for
the author J.K. Rowling, because we've decided not
to carry Harry Potter books (we just
don't want that kind of business), we could issue
the following statement:DELETE FROM books
WHERE author_id =
(SELECT authors.rec_id FROM authors
WHERE author_last = 'Rowling'
AND author_first = 'J.K.');
DELETE FROM authors
WHERE author_last = 'Rowling'
AND author_first = 'J.K.';SELECT
statement, the subquery contained in the parentheses. This statement
involves a subquery, so it requires Version 4.1 or later of MySQL. To
delete these same rows with an earlier version of MySQL, you would
need to run the SELECT statement shown here
separately (not as a subquery), make note of the
author's identification number, and then run the
first DELETE statement, manually entering the
identification number at the end instead of the parenthetical
SELECT statement shown.SET @potter =
(SELECT rec_id FROM authors
WHERE author_last = 'Rowling'
AND author_first = 'J.K.');
DELETE FROM books
WHERE author_id = @potter;
DELETE FROM authors
WHERE rec_id = @potter;SET statement to
establish a variable called @potter that will
contain the results of the SELECT statement that
follows in parentheses, another subquery. Incidentally, although this
subquery is not available before Version 4.1, user-defined variables
are. The second SQL statement deletes the rows from
books where the author identification number
matches the value of the temporary variable. Next we delete the data
from the authors table, still making use of the
variable. A user-defined variable will last until
it's reset or until the MySQL session is closed.SELECT
statements. Also, sometimes we don't have the exact
or complete text for a column in which we're
looking. For these situations, we can use the LIKE
operator. Suppose that our books table now has
thousands of entries. Suppose further that a customer says
he's looking for a specific book. He
can't remember the author or the title, but he does
remember that the words traveler and
winter are in the title. We could enter this
statement to search the database based on this minimal information:SELECT books.rec_id, title,
CONCAT(author_first, ' ', author_last) AS author
FROM books, authors
WHERE title LIKE '%traveler%'
AND title LIKE '%winter%'
AND author_id = authors.rec_id;
+--------+-----------------------------------+---------------+
| rec_id | title | author |
+--------+-----------------------------------+---------------+
| 1400 | If on a winter's night a traveler | Italo Calvino |
+--------+-----------------------------------+---------------+LIKE
operator, we use the percent-sign wildcard twice to indicate that
we're searching for all rows in which the title
column's data starts with zero or more characters
before the pattern of traveler is found, and
then zero or more characters may follow. Put another way, the word
traveler must be contained somewhere in the
column's data to have a pattern match. Also,
winter must be found in the column.
Incidentally, the LIKE keyword is an operator. For
more information on operators, see Appendix B.OR operator within an expression like so:SELECT books.rec_id, title,
CONCAT(author_first, ' ', author_last) AS author
FROM books, authors
WHERE title LIKE '%Ford%' AND author_id = authors.rec_id
OR title LIKE '%Chevrolet%' AND author_id = authors.rec_id;INSERT and REPLACE
statements are useful, they can be time-consuming when
you're entering a large number of rows, because
they're somewhat manual methods of entering data.
Often, when setting up a new database, you will need to migrate data
from an old database to MySQL. In the case of our bookstore,
let's suppose that a vendor has sent us a disk with
a list of all of their books in a simple text file. Each record for
each book is on a separate line and each field of each record is
separated by a vertical bar. Here's how the
fictitious vendor's data text file looks:ISBN|TITLE|AUTHOR LAST|AUTHOR FIRST|COPYRIGHT DATE| 067973452X|Notes from Underground|Dostoevsky|Fyodor|August 1994| ...
LOAD DATA INFILE statement from the
mysql client:LOAD DATA INFILE '/tmp/books.txt' REPLACE INTO TABLE authors FIELDS TERMINATED BY '|' LINES TERMINATED BY '\r\n' TEXT_FIELDS(col1, col2, col3, col4, col5) SET author_last = col3, author_first = col4 IGNORE col1, col2, col5, 1 LINES;
TEXT_FIELDS and the IGNORE
clause for columns are not available before Version 4.1 of MySQL. The
IGNORE n
LINESmysql --user='tina' --password='muller' \
-e "SELECT vendor, telephone FROM vendors \
WHERE state='LA'" bookstore-e switch to indicate that
what follows it in quotes is to be executed by the
mysql client. Notice that
what's in double quotes is the same SQL statement in
the same syntax as we would enter it in monitor mode. Finally, we
provide the name of the database