Chapter 3

Database for $100, Please

IN THIS CHAPTER

check Understanding some basic database concepts

check Taking a quick look at SQL

check Creating tables

check Selecting data

check Joining data

check Updating and deleting data

SQL stands for Structured Query Language. SQL is the lingua franca (that’s not a type of pasta but a type of tongue) of relational databases. It’s the standard language used for creating and accessing relational databases and is the foundation of database processing in Java.

Java provides Java Database Connectivity (JDBC), which lets you formulate SQL statements, send them off to a database server, and process the results. To use JDBC, however, you need to know some basic concepts of SQL databases and at least enough SQL to formulate some sensible SQL statements.

This chapter won’t make you a database guru or an expert on SQL — a complicated language that’s the subject of many entire books, including SQL For Dummies, 8th Edition, by Allen G. Taylor (Wiley). This chapter covers just enough SQL to get you going with JDBC.

Also, this chapter doesn’t cover JDBC. I decided to save that topic for Book 8, Chapter 4, so if you already know SQL, you can skip this chapter.

Defining a Relational Database

The term relational database is one of the most used and abused buzzwords in all of computerdom. A relational database can be

  • A database in which data is stored in tables: Relationships can be established between tables based on common information. A table of customers and a table of invoices, for example, might both contain a customer-number column. This column can serve as the basis for a relationship between the tables.
  • A database that is accessed via SQL: IBM invented SQL to provide a practical way to access data stored in relational databases.

From a Java programmer’s perspective, the second definition is the only one that matters. If you can use SQL to access the database, the database is relational.

Understanding (and Pronouncing) SQL

SQL is a query language, which means that it’s designed to extract, organize, and update information in relational databases. Way back in the 1970s, when it was invented (SQL is old enough to be Java’s grandfather), SQL was supposed to be an English-like query language that untrained users could employ to access and update relational database data without the need for programming. That didn’t happen, of course. SQL is nothing like English. It’s way too complicated and esoteric for untrained users to figure out. But it has become the overwhelming favorite among programmers.

Ever since you first saw the acronym SQL, you’ve probably been wondering how to pronounce it. (If not, humor me.) Two schools of thought exist on this subject:

  • Spell out the letters: Ess-Queue-El.
  • Pronounce it like the word sequel.

Either one does the job, but be warned: Some people are adamant that it must be pronounced one way or the other. Those people also tend to hold the opinion that anyone who pronounces it the “wrong” way (in their opinion) is an illiterate dweeb.

Introducing SQL Statements

Unlike Java, SQL is not object-oriented. Remember, SQL was invented during the Nixon administration. Like Java, however, SQL uses statements to get work done. Table 3-1 lists the SQL statements you use most often.

TABLE 3-1 Common SQL Statements

SQL Statement

Description

Data Manipulation

select

Retrieves data from one or more tables. This statement is the one you use most often.

insert

Inserts one or more rows into a table.

delete

Deletes one or more rows from a table.

update

Updates existing rows in a table.

Data Definition

create

Creates tables and other database objects.

alter

Changes the definitions of a table or other database object.

drop

Deletes a table or other database object.

use

In scripts, indicates what database subsequent statements apply to.

remember Unlike Java statements, statements in SQL aren’t case-sensitive, which means that you can write select, Select, or SELECT. You can even write sElEcT for kicks, if you want.

Creating a SQL Database

Before you can store data in a relational database, you must create the database. Normally you don’t do that from a Java program. Instead, you do it by writing a script file that contains the Create statements necessary to create the table and then running the script through the database server’s administration program. (Some database servers also let you define databases interactively, but the script approach is preferred because you often need to delete and re-create a database while testing your applications.)

tip The scripts shown in this section (and in the rest of this chapter) are for version 5.5 of MySQL. MySQL is a free SQL database server that you can download from dev.mysql.com/downloads/mysql. The complete MySQL download includes both the server and a handy program called the MySQL Command Line Client, which lets you enter SQL commands from a prompt and see the results immediately. (To install MySQL, go to the website mentioned at the start of this paragraph, click the link for the installer that’s appropriate for your Windows version, and then follow the onscreen instructions.)

remember Script statements end with semicolons, which is about the only thing that SQL scripts have in common with Java scripts. Be aware, however, that the semicolon isn’t required when you use SQL statements in a Java program. The semicolon is required only when you use SQL statements in a script or interactively from the MySQL Command Line Client program.

I don’t have room in this book to provide a complete tutorial on writing scripts that create SQL databases. Instead, I present Listing 3-1 — a sample script that creates a database named movies, which I use in the rest of this chapter and the next one — and walk you through its most important lines.

LISTING 3-1 A Database Creation Script

drop database if exists movies; →1
create database movies; →2
use movies; →3
create table movie ( →4
id int not null auto_increment, →5
title varchar(50), →6
year int, →7
price decimal(8,2), →8
primary key(id) →9
);
insert into movie (title, year, price) →11
values ("It's a Wonderful Life", 1946, 14.95);
insert into movie (title, year, price)
values ("Young Frankenstein", 1974, 16.95);
insert into movie (title, year, price)
values ("Star Wars", 1977, 17.95);
insert into movie (title, year, price)
values ("The Princess Bride", 1987, 16.95);
insert into movie (title, year, price)
values ("Glory", 1989, 14.95);
insert into movie (title, year, price)
values("The Game",1997,14.95);
insert into movie (title, year, price)
values("Shakespeare in Love",1998,19.95);
insert into movie (title, year, price)
values("Zombieland",2009,18.95);
insert into movie (title, year, price)
values("The King's Speech",2010,17.85);
insert into movie (title, year, price)
values("Star Trek Into Darkness",2013,19.95);

The following paragraphs describe the important lines of this script:

  1. →1 It’s common for a script that creates a database to begin with a drop database statement to delete any existing database with the same name. During testing, it’s common to delete and re-create the database, so you want to include this statement in your scripts.
  2. →2 This statement creates a new database named movies.
  3. →3 The use statement indicates that the script statements that follow apply to the newly created movies database.
  4. →4 This create table statement creates a table named movie with columns named id, title, year, and price. This statement also specifies that the primary key for the table is the id column.
  5. →5 The id column’s data type is int, which corresponds to Java’s int type. This column also specifies not null, which means that it must have a value for every row, and it specifies auto increment, which means that the database server itself provides values for this column. Each time a new row is added to the table, the value for the id column is incremented automatically.
  6. →6 The title column’s data type is varchar, which is like a Java String.
  7. →7 The year column’s data type is int.
  8. →8 The price column’s data type is decimal. Java doesn’t have a decimal type, so the values from this column are converted to double.
  9. →9 The create table statement specifies that the id column is the table’s primary key. A primary key is a column (or a combination of columns) containing a unique value for each row in a table. Every table should have a primary key.
  10. →11 The insert statements add data to the database. Each of these ten statements adds a row to the movie table. The syntax of the insert statements is weird, because you first list all the columns that you want to insert data for and then list the actual data. Each of the insert statements, for example, inserts data for three columns: title, year, and price. The first insert statement (the one in line 12) inserts the values "It's a Wonderful Life", 1946, and 14.95.

To run this script in MySQL, start the MySQL Command Line Client from the Start menu and then use a source command that names the script, as in this example:

mysql> source c:datacreate.sql

Note that the first time you run this script, you see an error message indicating that the movies database can’t be dropped because it doesn’t exist. You can safely ignore this error.

Querying a Database

As the name Structured Query Language suggests, queries are what SQL is all about. A query is an operation performed against one or more SQL tables; it extracts data from the tables and creates a result set, which contains the selected rows and columns.

remember A crucial point to understand is that the result set is itself a table consisting of rows and columns. When you query a database from a Java program, the result set is returned to the program in an object created from the ResultSet class. This class has methods that let you extract the data from each column of each row in the result set.

Using a basic select statement

To query a database, you use the select statement. In this statement, you list the table or tables from which you want to retrieve the data; the specific table columns you want to retrieve (you may not be interested in everything that’s in the table); and other clauses that indicate which rows to retrieve, what order to present the rows in, and so on. Here’s a simple select statement that lists all the movies in the movie table:

select title, year
from movie
order by year;

In the following list, I take this statement apart piece by piece:

  • select title, year names the columns you want to include in the query result.
  • from movie names the table from which you want to retrieve the rows.
  • order by year indicates that the result is sorted by the year column so that the oldest movie appears first.

In other words, this select statement retrieves the title and year for all the rows in the movie table and sorts them in year sequence. You can run this query by typing it directly in the Command Line Client. Here’s what you get:

mysql> select title, year from movie order by year;
+-------------------------+------+
| title | year |
+-------------------------+------+
| It's a Wonderful Life | 1946 |
| Young Frankenstein | 1974 |
| Star Wars | 1977 |
| The Princess Bride | 1987 |
| Glory | 1989 |
| The Game | 1997 |
| Shakespeare in Love | 1998 |
| Zombieland | 2009 |
| The King's Speech | 2010 |
| Star Trek Into Darkness | 2013 |
+-------------------------+------+
10 rows in set (0.00 sec)

As you can see, the Command Line Client displays the rows returned by the select statement. This feature can be very handy when you’re planning the select statements that your program needs, or when you’re testing a program that updates a table and want to make sure that the updates are made correctly.

If you want the query to retrieve all the columns in each row, you can use an asterisk instead of naming the individual columns, like so:

select * from movie order by year;

warning Using an asterisk in this manner isn’t a good idea, however, because the columns that make up the table may change. If you use an asterisk, your program can’t deal with changes in the table’s structure.

remember Both examples so far include an order by clause. In a SQL database, the rows stored in a table aren’t assumed to be in any particular sequence. As a result, if you want to display the results of a query in sequence, you must include an order by in the select statement.

Narrowing the query

Suppose that you want to find information about one particular video title. To select certain rows from a table, use the where clause in a select statement, as in this example:

mysql> select title, year from movie
-> where year <= 1980
-> order by year;
+-----------------------+------+
| title | year |
+-----------------------+------+
| It's a Wonderful Life | 1946 |
| Young Frankenstein | 1974 |
| Star Wars | 1977 |
+-----------------------+------+
3 rows in set (0.00 sec)

Here the select statement selects all the rows in which the year column is less than or equal to 1980. The results are ordered by the year column.

Excluding rows

Perhaps you want to retrieve all rows except those that match certain criteria. Here’s a query that ignores movies made in the 1970s (which is probably a good idea):

mysql> select title, year from movie
-> where year < 1970 or year > 1979
-> order by year;
+-------------------------+------+
| title | year |
+-------------------------+------+
| It's a Wonderful Life | 1946 |
| The Princess Bride | 1987 |
| Glory | 1989 |
| The Game | 1997 |
| Shakespeare in Love | 1998 |
| Zombieland | 2009 |
| The King's Speech | 2010 |
| Star Trek Into Darkness | 2013 |
+-------------------------+------+
8 rows in set (0.01 sec)

Using singleton selects

When you want to retrieve information for a specific row, mention the primary key column in the where clause, like this:

mysql> select title, year from movie where id = 7;
+---------------------+------+
| title | year |
+---------------------+------+
| Shakespeare in Love | 1998 |
+---------------------+------+
1 row in set (0.49 sec)

Here the where clause selects the row whose id column equals 7. This type of select statement is called a singleton select because it retrieves only one row. Singleton selects are commonly used in Java programs to allow users to access or update a specific database row.

Finding what something sounds like

Suppose that you want to retrieve information about a movie and can’t quite remember the name, but you know that it includes the word princess. One of the most interesting variations of the where clause throws in the word like, which lets you search rows using wildcards. Here’s an example in which the percent sign (%) is a wildcard character:

mysql> select title, year from movie
-> where title like "%princess%";
+--------------------+------+
| title | year |
+--------------------+------+
| The Princess Bride | 1987 |
+--------------------+------+
1 row in set (0.01 sec)

Using column functions

What if you want a count of the total number of movies in the movie table or a count of the number of movies that were made before 1970? To do that, you use a column function. SQL’s column functions let you make calculations on columns. You can calculate the sum, average, or largest or smallest value, or count the number of values for an entire column.

Table 3-2 summarizes these functions. Note: The functions operate on the values returned in a result set, which isn’t necessarily the entire table.

TABLE 3-2 Column Functions

Function

Description

sum(column-name)

Adds the values in the column.

avg(column-name)

Calculates the average value for the column. Null values aren’t included in the calculation.

min(column-name)

Determines the lowest value in the column.

max(column-name)

Determines the highest value in the column.

count(column-name)

Counts the number of rows that have data values for the column.

countDistinct(column-name)

Counts the number of distinct values for the column.

count(*)

Counts the number of rows in the result set.

To use one of these functions, specify the function rather than a column name in a select statement. The following select statement calculates the number of rows in the table and the year of the oldest movie:

mysql> select count(*), min(year) from movie;
+----------+-----------+
| count(*) | min(year) |
+----------+-----------+
| 10 | 1946 |
+----------+-----------+
1 row in set (0.00 sec)

As you can see, ten movies are in the table, and the oldest was made in 1946.

If the select statement includes a where clause, only the rows that match the criteria are included in the calculation. This statement finds out how many movies in the table were made before 1970:

mysql> select count(*) from movie where year < 1970;
+----------+
| count(*) |
+----------+
| 1 |
+----------+
1 row in set (0.00 sec)

The result is 2.

Selecting data from more than one table

In the real world, most select statements retrieve data from two or more tables. Suppose that you want a list of all the movies you’ve currently loaned out to friends. To do that, you have to create another table in your database that lists your friends’ names and the ids of any movies they’ve borrowed. Here’s a create table statement that creates just such a table:

create table friend (
lastname varchar(50),
firstname varchar(50),
movieid int
);

Now load it up with some data, like so:

insert into friend (lastname, firstname, movieid)
values ("Haskell", "Eddie", 3);
insert into friend (lastname, firstname, movieid)
values ("Haskell", "Eddie", 5);
insert into friend (lastname, firstname, movieid)
values ("Cleaver", "Wally", 9);
insert into friend (lastname, firstname, movieid)
values ("Mondello", "Lumpy", 2);
insert into friend (lastname, firstname, movieid)
values ("Cleaver", "Wally", 3);

With that out of the way, you can get to the business of using both the friend and movie tables in a single select statement. All you have to do is list both tables in the from clause and then provide a condition in the where clause that correlates the tables, as follows:

mysql> select lastname, firstname, title
-> from movie, friend
-> where movie.id = friend.movieid;
+----------+-----------+--------------------+
| lastname | firstname | title |
+----------+-----------+--------------------+
| Haskell | Eddie | Star Wars |
| Haskell | Eddie | Glory |
| Cleaver | Wally | The King's Speech |
| Mondello | Lumpy | Young Frankenstein |
| Cleaver | Wally | Star Wars |
+----------+-----------+--------------------+
5 rows in set (0.00 sec)

Here you can see which movies have been loaned out and who has them. Notice that the id and movieid columns in the where clause are qualified with the name of the table the column belongs to.

Here’s a select statement that lists all the movies Eddie Haskell has borrowed:

mysql> select title from movie, friend
-> where movie.id = friend.movieid
-> and lastname = "Haskell";
+-----------+
| title |
+-----------+
| Star Wars |
| Glory |
+-----------+
2 rows in set (0.00 sec)

That rat has two of your best movies!

Notice in this example that you can refer to the friend table in the where clause, even though you’re not actually retrieving any of its columns. You must still mention both tables in the from clause, however.

Eliminating duplicates

If you want to know just the names of all your friends who have a movie checked out, you can do a simple select from the friend table, like this:

mysql> select lastname, firstname from friend;
+----------+-----------+
| lastname | firstname |
+----------+-----------+
| Haskell | Eddie |
| Haskell | Eddie |
| Cleaver | Wally |
| Mondello | Lumpy |
| Cleaver | Wally |
+----------+-----------+
5 rows in set (0.00 sec)

This result set has a problem, however: Eddie Haskell and Wally Cleaver are listed twice. Wouldn’t it be nice if you could eliminate the duplicate rows? Your wish is granted in the next paragraph.

tip You can eliminate duplicate rows by adding the distinct keyword in the select statement, as follows:

mysql> select distinct lastname, firstname from friend;
+----------+-----------+
| lastname | firstname |
+----------+-----------+
| Haskell | Eddie |
| Cleaver | Wally |
| Mondello | Lumpy |
+----------+-----------+
3 rows in set (0.07 sec)

Notice that no duplicates appear; each distinct name appears only once in the result set.

Updating and Deleting Rows

You’ve already seen how to create databases, insert rows, and retrieve result sets. All that remains now is updating and deleting data in a table. For that, you use the update and delete statements, as described in the following sections. I explain the delete statement first because its syntax is simpler.

Using the delete statement

The basic syntax of the delete statement is

delete from table-name where condition;

Here’s a statement that deletes the movie whose id is 10:

mysql> delete from movie where id = 10;
Query OK, 1 row affected (0.44 sec)

Notice that the Command Line Client shows that this statement affected one line. You can confirm that the movie was deleted by following up with a select statement, like so:

mysql> select * from movie;
+----+-----------------------+------+-------+
| id | title | year | price |
+----+-----------------------+------+-------+
| 1 | It's a Wonderful Life | 1946 | 14.95 |
| 2 | Young Frankenstein | 1974 | 16.95 |
| 3 | Star Wars | 1977 | 17.95 |
| 4 | The Princess Bride | 1987 | 16.95 |
| 5 | Glory | 1989 | 14.95 |
| 6 | The Game | 1997 | 14.95 |
| 7 | Shakespeare in Love | 1998 | 19.95 |
| 8 | Zombieland | 2009 | 18.95 |
| 9 | The King's Speech | 2010 | 17.85 |
+----+-----------------------+------+-------+
9 rows in set (0.00 sec)

As you can see, movie 10 is gone.

If the where clause selects more than one row, all the selected rows are deleted, as in this example:

mysql> delete from friend where lastname = "Haskell";
Query OK, 2 rows affected (0.45 sec)

A quick query of the friend table shows that both records for Eddie Haskell are deleted, like so:

mysql> select * from friend;
+----------+-----------+---------+
| lastname | firstname | movieid |
+----------+-----------+---------+
| Cleaver | Wally | 9 |
| Mondello | Lumpy | 2 |
| Cleaver | Wally | 3 |
+----------+-----------+---------+
3 rows in set (0.00 sec)

warning If you don’t include a where clause, the entire table is deleted. This statement deletes all the rows in the movie table:

mysql> delete from movie;
Query OK, 9 rows affected (0.44 sec)

A quick select of the movie table confirms that it is now empty, as follows:

mysql> select * from movie;
Empty set (0.00 sec)

Fortunately, you can just run the create.sql script again to create the table.

Using the update statement

The update statement selects one or more rows in a table and then modifies the value of one or more columns in the selected rows. Its syntax is this:

update table-name
set expressions
where condition;

The set expressions resemble Java assignment statements. Here’s a statement that changes the price of movie 8 to 18.95:

mysql> update movie set price = 18.95 where id = 8;
Query OK, 1 row affected (0.44 sec)
Rows matched: 1 Changed: 1 Warnings: 0

You can use a quick select statement to verify that the price was changed, as follows:

mysql> select id, price from movie;
+----+-------+
| id | price |
+----+-------+
| 1 | 14.95 |
| 2 | 16.95 |
| 3 | 17.95 |
| 4 | 16.95 |
| 5 | 14.95 |
| 6 | 14.95 |
| 7 | 19.95 |
| 8 | 18.95 |
| 9 | 17.85 |
+----+-------+
9 rows in set (0.00 sec)

To update more than one column, use commas to separate the expressions. Here’s a statement that changes Eddie Haskell’s name in the friend table:

mysql> update friend set lastname = "Bully",
-> firstname = "Big"
-> where lastname = "Haskell";
Query OK, 2 rows affected (0.46 sec)
Rows matched: 2 Changed: 2 Warnings: 0

Again, a quick select shows that the rows are properly updated, as follows:

mysql> select firstname, lastname from friend;
+-----------+----------+
| firstname | lastname |
+-----------+----------+
| Big | Bully |
| Big | Bully |
| Wally | Cleaver |
| Lumpy | Mondello |
| Wally | Cleaver |
+-----------+----------+
5 rows in set (0.00 sec)

One final trick with the update statement you should know about is that the set expressions can include calculations. The following statement increases the prices of all the movies by 10 percent:

mysql> update movie set price = price * 1.1;
Query OK, 10 rows affected (0.46 sec)
Rows matched: 10 Changed: 10 Warnings: 0

Here’s a select statement to verify that this update worked:

mysql> select id, price from movie;
+----+-------+
| id | price |
+----+-------+
| 1 | 16.45 |
| 2 | 18.65 |
| 3 | 19.75 |
| 4 | 18.65 |
| 5 | 16.45 |
| 6 | 16.45 |
| 7 | 21.95 |
| 8 | 20.85 |
| 9 | 19.64 |
| 10 | 21.95 |
+----+-------+
10 rows in set (0.01 sec)

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

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