Chapter 7:Retrieving Data with SQL Queries colNames = dbUtils.getColumnNamestableName; dataTypes = dbUtils.getDataTypestableName; SQLQuery = "SELECT TOP 5 * FROM "+tableName; Vector
Trang 1Chapter 7:Retrieving Data with SQL Queries
* CREATE statements
*/
class TableQueryFrame extends JInternalFrame{
protected JTable table;
protected JScrollPane tableScroller;
protected JTextArea SQLPane = new JTextArea();
protected JButton queryButton = new JButton("Execute Query");
protected DatabaseUtilities dbUtils;
protected String tableName = null;
protected String colNames[] = null;
protected String dataTypes[] = null;
protected String SQLQuery = null;
protected String SQLCommandRoot = "";
Trang 2Chapter 7:Retrieving Data with SQL Queries
colNames = dbUtils.getColumnNames(tableName);
dataTypes = dbUtils.getDataTypes(tableName);
SQLQuery = "SELECT TOP 5 * FROM "+tableName;
Vector dataSet = dbUtils.executeQuery(SQLQuery);
table = createTable(colNames,dataSet);
JScrollPane sqlScroller = new JScrollPane(SQLPane);
tableScroller = new JScrollPane(table);
JSplitPane splitter = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
protected JTable createTable(String[] colNames,Vector dataSet){
int nRows = dataSet.size();
String[][] rowData = new String[nRows][colNames.length];
// Listener for the Query Button
class ButtonListener implements ActionListener{
public void actionPerformed(ActionEvent event){
Trang 3Chapter 7:Retrieving Data with SQL Queries
public class DBManager extends JFrame{
JMenuBar menuBar = new JMenuBar();
JDesktopPane desktop = new JDesktopPane();
String database = null;
String tableName = null;
String menuSelection = null;
TableBuilderFrame tableMaker = null;
TableEditFrame tableEditor = null; // added for Chapter 6
TableQueryFrame tableQuery = null; // added for Chapter 7
DatabaseUtilities dbUtils = null;
TableMenu tableMenu = new TableMenu();
EditMenu editMenu = new EditMenu(); // added for Chapter 6
ViewMenu viewMenu = new ViewMenu(); // added for Chapter 7
MenuListener menuListener = new MenuListener();
Trang 4Chapter 7:Retrieving Data with SQL Queries
Trang 5Chapter 7:Retrieving Data with SQL Queries
private String[] parseKeyValueString(String kvString){
String[] kvPair = null;
Trang 6Chapter 7:Retrieving Data with SQL Queries
int option = JOptionPane.showConfirmDialog(null,
"Dropping table "+tableName,
class MenuListener implements ActionListener{
public void actionPerformed(ActionEvent event){
String menuSelection = event.getActionCommand();
Trang 7Chapter 7:Retrieving Data with SQL Queries
}else if(menuSelection.equals("ResultSet")){ // added for Chapter 7
class ExceptionListener implements ActionListener{
public void actionPerformed(ActionEvent event){
String exception = event.getActionCommand();
class CommandListener implements ActionListener{
public void actionPerformed(ActionEvent event){
String SQLCommand = event.getActionCommand();
executeSQLCommand(SQLCommand);
}
}
public static void main(String args[]){
DBManager dbm = new DBManager();
Trang 8Chapter 7:Retrieving Data with SQL Queries
String array of column names pertinent to the query, rather than all the column names for the entire table
public class DatabaseUtilities{
static String jdbcDriver = "sun.jdbc.odbc.JdbcOdbcDriver";
static String dbName = "Contacts";
static String urlRoot = "jdbc:odbc:";
private ActionListener exceptionListener = null;
Trang 9Chapter 7:Retrieving Data with SQL Queries
}
public void execute(String SQLCommand){
String url = urlRoot+dbName;
public void execute(String[] SQLCommand){
String url = urlRoot+dbName;
public String[] getColumnNames(String tableName){
Vector dataSet = new Vector();
String[] columnNames = null;
String url = urlRoot+dbName;
String SQLCommand = "SELECT * FROM "+tableName+";";
Trang 10Chapter 7:Retrieving Data with SQL Queries
Connection con = DriverManager.getConnection(url);
public String[] getColumnNamesUsingQuery(String SQLCommand){
Vector dataSet = new Vector();
String[] columnNames = null;
String url = urlRoot+dbName;
Trang 11Chapter 7:Retrieving Data with SQL Queries
reportException(e.getMessage());
}
return columnNames;
}
public String[] getDataTypes(String tableName){
Vector dataSet = new Vector();
String[] dataTypes = null;
String url = urlRoot+dbName;
String SQLCommand = "SELECT * FROM "+tableName+";";
public Vector executeQuery(String SQLQuery){
Vector dataSet = new Vector();
String url = urlRoot+dbName;
try {
Trang 12Chapter 7:Retrieving Data with SQL Queries
§ What a Query is and how to create and execute one
Trang 13Chapter 7:Retrieving Data with SQL Queries
§ Using SELECT FROM to retrieve all rows and columns from a table
§ Using the WHERE clause to retrieve rows matching a specific query
§ Using the ORDER BY clause to sort the returned data
§ SQL Operators
§ Escape sequences
§ Subqueries using the keywords:
§ EXISTS and NOT EXISTS
§ ANY and ALL
§ IN and NOT IN
§ Nested and correlated subqueries
§ JDBC ResultSets and ResultSetMetaData The next chapter discusses using joins to retrieve data from more than one table
Trang 14Chapter 8:Organizing Search Results and Using Indexes
Chapter 8: Organizing Search Results and Using Indexes
In This Chapter
This chapter discusses various ways of organizing and analyzing the data returned by SQL queries These include sorting the data by one or more columns, grouping the data and performing statistical analysis, and filtering the grouped results
The chapter also addresses the use of indexes to make your queries more efficient Using indexes wisely can result in a very significant improvement in performance, while using indexes incorrectly can result in very poor performance
The final topic discussed in this chapter is the use of Views Views provide a means of creating temporary tables based on a particular query
Using ORDER BY to Sort the Results of a Query
A common requirement when retrieving data from an RDBMS by using the SELECT statement is to sort the results of the query in alphabetic or numeric order on one or more of the columns You sort the results by using the ORDER BY clause in a statement like this:
SELECT First_Name, Last_Name, City, State
Table 8-1: Records Sorted Using ORDER BY
The default sort order is ascending This can be changed to descending order by adding the DESC keyword as shown in the next example:
Note
The keywords ASC and DESC can be used to specify ascending or descending sort
Trang 15Chapter 8:Organizing Search Results and Using Indexes
order
SELECT *
FROM CUSTOMERS
WHERE Last_Name = 'Corleone'
ORDER BY First_Name DESC;
Sorting on multiple columns is also easy to do by using a sort list For example, to sort the data in ascending order based on Last_Name and then sort duplicates using the First_Name in descending order, the sort list is as follows:
ORDER BY Last_Name, First_Name DESC;
The entire SQL statement to sort the data in ascending order based on Last_Name and then sort duplicates using the First_Name in descending order is shown below
SELECT First_Name, MI, Last_Name, Street, City, State, Zip
§ ORDER BY must be the last clause in the SELECT statement
§ Default sort order is ascending
§ You can specify ascending order with the keyword ASC
§ You can specify descending order with the keyword DESC
§ You can use column names or expressions in the ORDER BY clause
§ The column names in the ORDER BY clause do not have to be specified in the select list
§ NULLS usually occur first in the sort order
Note
The DatabaseMetaData object provides a number of methods:
boolean nullsAreSortedAtStart() boolean nullsAreSortedAtEnd() These methods can be used to determine the sort order for NULLs when in doubt.Another common reporting requirement is to break down the data a query returns into various groups
so that the data can be analyzed in some way The GROUP BY clause, discussed in the next section, enables you to combine database records to perform calculations such as averages or counts on groups of records
The GROUP BY Clause
Trang 16Chapter 8:Organizing Search Results and Using Indexes
The GROUP BY clause combines records with identical values in a specified field into a single record for this purpose, as shown in Figure 8-1, illustrating how to use GROUP BY to compute a count of
customers by state
Figure 8-1: Using GROUP BY to count customers by state
Because the GROUP BY clause combines all records with identical values in one column into a single record, each of the column names in the SELECT clause must be either a column specified in the GROUP BY clause or a column function such as COUNT() or SUM()
This means that you can't SELECT a list of individual customers by name and then count them as a group by using GROUP BY However, you can group on more than one column, just as you can use more than one column with the ORDER BY clause You can see an example of the use of GROUP BY on more than one column in Figure 8-2
Figure 8-2: Using GROUP BY on multiple columns
Note
Every column name specified in the SELECT statement is also mentioned in the GROUP
BY clause Not mentioning the column names in both places gives you an error The GROUP BY clause returns a row for each unique combination of description and state
Trang 17Chapter 8:Organizing Search Results and Using Indexes
The most important uses of the GROUP BY clause is to group data for analytical purposes The
functions used to analyze groups of data are called aggregate functions The aggregate functions are
discussed in the next section
Aggregate Functions
Aggregate functions return a single value from an operation on a column of data This differentiates
them from the arithmetic, logical, and character functions discussed in Chapter 7, which operate on individual data elements Most relational database management systems support the aggregate functions listed in Table 8-2
Table 8-2: Commonly Supported Aggregate Functions
A good practical example of the use of aggregate functions is the creation of a simple sales report In Figure 8-3, the query creates a result set listing distinct customers and calculating the number and total cost of the items they have bought
Figure 8-3: Using aggregate functions
Trang 18Chapter 8:Organizing Search Results and Using Indexes
Since this example groups order data by customer, each row of the result set represents a single customer so that customer information can be displayed The aggregate functions act on all the purchases customers have made, so they, too, can be included in the SELECT list:
Note
The fundamental difference between aggregate functions and standard functions is that aggregate functions use the entire column of data as their input and produce a single output, whereas standard functions operate on individual data elements
In addition to using the GROUP BY clause to group your results, you may also wish to narrow your set of groups down to a smaller subset You can filter grouped data by using the HAVING clause, which is discussed in the next section
Using the HAVING Clause to Filter Groups
There are going to be situations where you'll want to filter the groups themselves in much the same way as you filter records using the WHERE clause For example, you may want to analyze your sales by state but ignore states with a limited number of customers
SQL provides a way of filtering groups in a result set using the HAVING clause The HAVING clause works in much the same way as the WHERE clause, except that it applies to groups within a returned result set, rather than to the entire table or group of tables forming the subject of a SELECT statement
To filter groups, apply a HAVING clause after the GROUP BY clause The HAVING clause lets you apply
a qualifying condition to groups so that the database management system returns a result only for the groups that satisfy the condition Incidentally, you can also apply a HAVING clause to the entire result set by omitting the GROUP BY clause In this case, DBMS treats the entire table as one group, so there
is at most one result row If the HAVING condition is not true for the table as a whole, no rows will be returned
HAVING clauses can contain one or more predicates connected by ANDs and ORs Each predicate compares a property of the group (such as COUNT(State)) with either another property of the group
or a constant
Figure 8-4 shows the use of the HAVING clause to compute a count of customers by state, filtering results from states that contain only one customer
Trang 19Chapter 8:Organizing Search Results and Using Indexes
Figure 8-4: Using the HAVING clause
The main similarity between the HAVING clause and the WHERE clause is that both allow you to use a variety of filters in a query The main difference is that the HAVING clause applies to groups within a returned result set, while the WHERE clause applies to the entire table or group of tables forming the subject of a SELECT statement
Using Indexes to Improve the Efficiency of SQL Queries
You can improve database performance significantly by using indexes An index is a structure that
provides a quick way to look up specific items in a table or view In effect, an index is an ordered array
of pointers to the rows in a table or view
When you assign a unique id to each row as a key, you are predefining an index for that table This makes it much faster for the DBMS to look up items by id, which is commonly required when you are doing joins on the id column
SQL's CREATE INDEX statement allows you to add an index for any desired column or group of columns When you need to do a search by customer name, for example, the unique row id buys you nothing; the DBMS has to do a brute-force search of the entire table to find all customer names matching your query If you plan on doing a lot of queries by customer name, it obviously makes sense
to add an index to the customer name column or columns Otherwise, you are in the position of someone working with a phone list that hasn't been alphabetized
The SQL command to add an index uses the CREATE INDEX keyword, specifying a name for the index and defining the table name and the column list to index Here's an example:
CREATE INDEX STATE_INDEX ON MEMBER_PROFILES(STATE);
To remove the index, use the DROP INDEX command
DROP INDEX MEMBER_PROFILES.STATE_INDEX;
Notice how the name of the index has to be fully defined by prefixing it with the name of the table to which it applies
Trang 20Chapter 8:Organizing Search Results and Using Indexes
The example in Listing 8-1 is a simple JDBC, with a couple of lines of additional code that calculate the start and stop times of the query so that the elapsed can be calculated By commenting out the
CREATE INDEX and DROP INDEX lines, speed improvement can easily be calculated
Listing 8-1: Creating and dropping indexes
package java_databases.ch04;
import java.sql.*;
public class PrintIndexedResultSet{
public static void main(String args[]){
String query =
"SELECT STATE, COUNT(STATE) FROM MEMBER_PROFILES GROUP BY STATE";
PrintIndexedResultSet p = new PrintIndexedResultSet(query);
Trang 21Chapter 8:Organizing Search Results and Using Indexes
for(int i=1;i<=nColumns;i++){
System.out.print(rs.getString(i)+((i==nColumns)?"\n":"\t"));
}
}
java.util.Date endTime = new java.util.Date();
long elapsedTime = endTime.getTime() - startTime.getTime();
System.out.println("Elapsed time: "+elapsedTime);
Once you have executed a SQL query and obtained a sorted, grouped set of data from the database, it
is frequently very useful to be able to save the query for reuse One of the ways SQL lets you do this is
by using Views
Views
A view is similar to a table, but rather than being created as a fundamental part of the underlying
database, it is created from the results of a query In fact, you can think of a view as a temporary table Like a table, a view has a name that can be used to access it in other queries Because views work like tables, they can be a very useful tool in simplifying SQL queries For example, you could create a view based on a complex JOIN, and then work with that view as a temporary table rather than embedding the JOIN as a subquery and working with the underlying tables
The basic syntax used to create a view is as follows:
CREATE VIEW Orders_by_Name AS SELECT
Trang 22Chapter 8:Organizing Search Results and Using Indexes
CREATE VIEW ViewCorleones AS
SELECT *
FROM CUSTOMERS
WHERE Last_Name = 'Corleone'
Now you can execute a query just as if this view were a normal table, as follows:
SELECT *
FROM ViewCorleones
The result set this query returns looks like this:
FIRST_NAME MI LAST_NAME STREET CITY STATE ZIP
Michael A Corleone 123 Pine New York NY 10006 Fredo X Corleone 17 Main New York NY 10007 Sonny A Corleone 123 Walnut Newark NJ 12346 Francis X Corleone 17 Main New York NY 10005
As with any other table, you can use more complex queries Here's an example:
SELECT *
FROM ViewCorleones
WHERE State = 'NJ'
This query returns the following result set:
FIRST_NAME MI LAST_NAME STREET CITY STATE ZIP
Sonny A Corleone 123 Walnut Newark NJ 12346
You can use a view for updating or deleting rows, as well as for retrieving data Since the view is not a table in its own right, but merely a way of looking at a table, rows updated or deleted in the view are updated or deleted in the original table For example, you can use the view to change Fredo Corleone's street address by using the following SQL statement:
UPDATE ViewCorleones
SET Street = '19 Main'
WHERE First_Name = 'Fredo'
This example illustrates one of the advantages of using a view A lot of the filtering required to identify the target row is done in the view, so the SQL code is simpler and more maintainable In a nontrivial example, this can be a worthwhile improvement
Trang 23Chapter 8:Organizing Search Results and Using Indexes
Figure 8-5 shows how using the view to the change Fredo Corleone's street address propagates through to the Customers Table
Figure 8-5: Updating a view updates the underlying table
Recall that a view is really nothing more than a named result set made accessible as if it were a table Creating a view from a complicated query is just as easy as creating one from a simple query
One way to retrieve data from multiple tables is to use an INNER JOIN The next example shows how
to use an INNER JOIN to retrieve data from four different tables, creating a view called
"Orders_by_Name":
CREATE VIEW Orders_by_Name AS
SELECT c.LAST_NAME + ', ' + c.FIRST_NAME AS Name,
COUNT(i.Item_Number) AS Items, SUM(oi.Qty * i.Cost)
JOINS are discussed in Chapter 9
You can now query this view in the normal way to get a summary of customer orders by name as shown in the following table
Trang 24Chapter 8:Organizing Search Results and Using Indexes
Views are a way of saving queries by name, which can be very useful for creating reports
or updates you want to use on a regular basis The database management system generally saves the view by associating the SELECT statement with the view name and executing it when you want to access the view
Summary
In this chapter, you learn to perform the following tasks:
§ Sorting the data you retrieve from a database
§ Grouping the results for analysis
§ Performing statistical analyses on the data you retrieve from a database
§ Create and use indexes to improve performance
§ Saving your queries as views
In the next chapter, you learn to retrieve data from more than one table
Trang 25Chapter 9:Joins and Compound Queries
Chapter 9: Joins and Compound Queries
In This Chapter
One of the most powerful features of SQL is its ability to combine data from several tables into a single result set When tables are combined in this way, the operation performed is called a JOIN There are two primary types of JOIN, and a number of different ways in which they can be performed
Another way to combine data from different tables into a single result set is to use the UNION operator This chapter discusses the different types of JOINS, and the use of the UNION operator
Joining Tables
Chapter 2 explained how an efficient and reliable database design frequently requires the information
in a practical database will be distributed across several tables, each of which contains sets of logically related data A typical example might be a database containing these four tables:
§ Customers, containing customer number, name, shipping address, and billing information
§ Inventory, containing item number, name, description, cost, and quantity on hand
§ Orders, containing order number, customer number, order date, and ship date
§ Ordered_Items, containing order number, item number, and quantity
When a customer places an order, an entry is made in the Orders Table, assigning an order number and containing the customer number and the order date Then entries are added to the Ordered_Items table, recording order number, item number, and quantity To fill a customer order, you need to
combine the necessary information from each of these tables
Using JOIN, you are able to combine data from these different tables to produce a detailed invoice
This invoice will show the customer name, shipping address, and billing information from the Customers table, combined with a detailed list of the items ordered from the Ordered_Items table, supported by detailed description, quantity, and unit price information from the inventory table
Cross-Reference
Primary and Foreign Keys are also discussed in Chapter 1, which provides
a more theoretical overview of Relational Database Management Systems
Types of Joins
There are two major types of Joins: Inner Joins and Outer Joins The difference between these two types of Joins goes back to the basic Set Theory underlying relational databases You can imagine the keys of two database tables, A and B as intersecting sets, as shown in Figure 9-1