Get Mastering Oracle SQL 1st Edition Sanjay Mishra Free All Chapters
Get Mastering Oracle SQL 1st Edition Sanjay Mishra Free All Chapters
com
https://ebookultra.com/download/mastering-oracle-
sql-1st-edition-sanjay-mishra/
https://ebookultra.com/download/mastering-oracle-sql-2nd-edition-
mishra/
ebookultra.com
https://ebookultra.com/download/pro-oracle-sql-expert-s-voice-in-
oracle-1st-edition-karen-morton/
ebookultra.com
https://ebookultra.com/download/mastering-oracle-scheduler-in-
oracle-11g-databases-1st-edition-ronald-rood/
ebookultra.com
https://ebookultra.com/download/oracle-pl-sql-programming-sixth-
edition-steven-feuerstein/
ebookultra.com
Beginning Oracle SQL 3rd Edition Lex De Haan
https://ebookultra.com/download/beginning-oracle-sql-3rd-edition-lex-
de-haan/
ebookultra.com
https://ebookultra.com/download/oracle-sql-loader-the-definitive-
guide-1st-edition-jonathan-gennick/
ebookultra.com
https://ebookultra.com/download/oracle-sql-tuning-pocket-
reference-1st-ed-edition-mark-gurry/
ebookultra.com
https://ebookultra.com/download/oracle-sql-plus-the-definitive-
guide-2nd-ed-edition-jonathan-gennick/
ebookultra.com
https://ebookultra.com/download/exper-t-oracle-sql-optimization-
deployment-and-statistics-1st-edition-tony-hasler-auth/
ebookultra.com
Mastering Oracle SQL 1st Edition Sanjay Mishra Digital
Instant Download
Author(s): Sanjay Mishra, Alan Beaulieu
ISBN(s): 9780596001292, 0596001290
Edition: 1
File Details: PDF, 4.61 MB
Year: 2002
Language: english
,TITLE.12934 Page i Wednesday, March 27, 2002 2:34 PM
O’Reilly & Associates books may be purchased for educational, business, or sales promotional
use. Online editions are also available for most titles (safari.oreilly.com). For more information
contact our corporate/institutional sales department: (800) 998-9938 or [email protected].
Printing History:
April 2002: First Edition.
Nutshell Handbook, the Nutshell Handbook logo, and the O’Reilly logo are registered
trademarks of O’Reilly & Associates, Inc. Many of the designations used by manufacturers and
sellers to distinguish their products are claimed as trademarks. Where those designations appear
in this book, and O’Reilly & Associates, Inc. was aware of a trademark claim, the designations
have been printed in caps or initial caps. Oracle® and all Oracle-based trademarks and logos are
trademarks or registered trademarks of Oracle Corporation, Inc., in the United States and other
countries. O’Reilly & Associates, Inc., is independent of Oracle Corporation. The association
between the image of a lantern fly and the topic of mastering Oracle SQL is a trademark of
O’Reilly & Associates, Inc.
While every precaution has been taken in the preparation of this book, the publisher and the
authors assume no responsibility for errors or omissions, or for damages resulting from the use of
the information contained herein.
ISBN: 0-596-00129-0
[M]
,AUTHOR.COLO.12460 Page 1 Wednesday, March 27, 2002 2:33 PM
Colophon
Our look is the result of reader comments, our own experimentation, and feedback
from distribution channels. Distinctive covers complement our distinctive approach
to technical topics, breathing personality and life into potentially dry subjects.
The insect on the cover of Mastering Oracle SQL is a lantern fly. The lantern fly is
mostly tropical, with a wingspan of up to six inches. The lantern fly’s elongated head is
an evolutionary adaptation called automimicry, in which parts of the body are disguised
or artifically shifted to other areas to confuse predators: the lantern fly’s head looks like
a tail, and its tail looks like a head. On the rear it has artificial eyes and antennae.
Colleen Gorman was the production editor and copyeditor for Mastering Oracle SQL.
Sheryl Avruch and Ann Schirmer provided quality control. Tom Dinse wrote the index.
Ellie Volckhausen and Emma Colby designed the cover of this book, based on a
series design by Edie Freedman. The cover image is a 19th-century engraving from
Johnson’s Natural History. Emma Colby produced the cover layout with Quark-
XPress 4.1 using Adobe’s ITC Garamond font.
David Futato designed the interior layout. Neil Walls converted the files from
Microsoft Word to FrameMaker 5.5.6 using tools written in Perl by Erik Ray, Jason
McIntosh, and Neil Walls, as well as tools written by Mike Sierra. The text font is
Linotype Birka; the heading font is Adobe Myriad Condensed; and the code font is
LucasFont’s TheSans Mono Condensed. The illustrations that appear in the book
were produced by Robert Romano and Jessamyn Read using Macromedia FreeHand
9 and Adobe Photoshop 6. The tip and warning icons were drawn by Christopher
Bing. This colophon was written by Colleen Gorman.
,DEDICATION.12802 Page iii Wednesday, March 27, 2002 2:34 PM
Table of Contents
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . viii
1. Introduction to SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
What Is SQL? 1
A Brief History of SQL 2
A Simple Database 4
DML Statements 4
3. Joins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Inner Joins 26
Outer Joins 30
Self Joins 37
Joins and Subqueries 42
DML Statements on a Join View 43
ANSI-Standard Join Syntax in Oracle9i 49
4. Group Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
Aggregate Functions 55
The GROUP BY Clause 59
The HAVING Clause 65
v
,mast_ora_sqlTOC.fm.10634 Page vi Wednesday, March 27, 2002 2:23 PM
5. Subqueries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
What Is a Subquery? 68
Noncorrelated Subqueries 69
Correlated Subqueries 75
Inline Views 77
Subquery Case Study: The Top N Performers 89
vi | Table of Contents
,mast_ora_sqlTOC.fm.10634 Page vii Wednesday, March 27, 2002 2:23 PM
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308
Preface
SQL, which stands for Structured Query Language, is the language for accessing a
relational database. SQL provides a set of statements for storing and retrieving data
to and from a relational database. It has gained steadily in popularity ever since the
first relational database was unleashed upon the world. Other languages have been
put forth, but SQL is now accepted as the standard language for almost all relational
database implementations, including Oracle.
SQL is different from other programming languages because it is nonprocedural.
Unlike programs in other languages, where you specify the sequence of steps to be
performed, a SQL program (more appropriately called a SQL statement) only
expresses the desired result. The responsibility for determining how the data will be
processed in order to generate the desired result is left to the database management
system. The nonprocedural nature of SQL makes it easier to access data in applica-
tion programs.
If you are using an Oracle database, SQL is the interface you use to access the data
stored in your database. SQL allows you to create database structures such as tables
(to store your data), views, and indexes. SQL allows you to insert data into the data-
base, and to retrieve that stored data in a desired format (for example, you might sort
it). Finally, SQL allows you to modify, delete, and otherwise manipulate your stored
data. SQL is the key to everything you do with the database. It’s important to know
how to get the most out of that interface. Mastery over the SQL language is one of
the most vital requirements of a database developer or database administrator.
viii
When we looked for help with SQL in the computer book market, we found that
there are really two types of SQL books available. Most are the reference type that
describe features and syntax, but that don’t tell you how to apply that knowledge to
real-life problems. The other type of book, very few in number, discusses the applica-
tion of SQL in a dry and theoretical style without using any particular vendor’s
implementation. Since every database vendor implements their own variation of
SQL, we find books based on “standard” SQL to be of limited usefulness.
In writing this book, we decided to write a practical book focused squarely on Oracle’s
version of SQL. Oracle is the market-leading database, and it’s also the database on
which we’ve honed our SQL expertise. In this book, we not only cover the most impor-
tant and useful of Oracle’s SQL features, but we show ways to apply them to solve spe-
cific problems.
Preface | ix
x | Preface
• Chapter 9, DECODE and CASE, talks about two very powerful yet simple fea-
tures of Oracle SQL that enable you to simulate conditional logic in what is oth-
erwise a declarative language. CASE, an ANSI standard construct, was first
introduced in Oracle8i, and was enhanced in Oracle9i.
• Chapter 10, Partitions, Objects, and Collections, discusses the issues involved
with accessing partitions and collections using SQL. Learn to write SQL state-
ments that operate on specific partitions and subpartitions. Also learn to query
object data, nested tables, and variable arrays.
• Chapter 11, PL/SQL, explores the integration of SQL and PL/SQL. This chapter
describes how to call PL/SQL stored procedures and functions from SQL state-
ments, and how to write efficient SQL statements within PL/SQL programs.
• Chapter 12, Advanced Group Operations, deals with complex grouping opera-
tions used mostly in decision support systems. We show you how to use Oracle
features such as ROLLUP, CUBE, and GROUPING SETS to efficiently generate
various levels of summary information required by decision support applica-
tions. We also discuss the new Oracle9i grouping features that enable compos-
ite and concatenated groupings, and the new GROUP_ID and GROUPING_ID
functions.
• Chapter 13, Advanced Analytic SQL, deals with analytical queries and new ana-
lytic functions. Learn how to use ranking, windowing, and reporting functions
to generate decision support information. This chapter also covers the new ana-
lytic features introduced in Oracle9i.
• Chapter 14, SQL Best Practices, talks about best practices that you should follow
in order to write efficient and maintainable queries. Learn which SQL constructs
are the most efficient for a given situation. For example, we describe when it’s
better to use WHERE instead of HAVING to restrict query results. We also dis-
cuss the performance implications of using bind variables vis-à-vis literal SQL.
Preface | xi
xii | Preface
You can also send messages electronically. To be put on the mailing list or request a
catalog, send email to:
[email protected]
To ask technical questions or comment on the book, send email to:
[email protected]
We have a web site for this book, where you can find examples and errata (previ-
ously reported errors and corrections are available for public view there). You can
access this page at:
http://www.oreilly.com/catalog/mastorasql
For more information about this book and others, see the O’Reilly web site:
http://www.oreilly.com
Acknowledgments
We are indebted to a great many people who have contributed in the development
and production of this book. We owe a huge debt of gratitude to Jonathan Gennick,
the editor of the book. Jonathan’s vision for this book, close attention to details, and
exceptional editing skills are the reasons this book is here today.
Our sincere thanks to our technical reviewers: Diana Lorentz, Jeff Cox, Stephan
Andert, Rich White, Peter Linsley, and Chris Lee, who generously gave their valu-
able time to read and comment on a draft copy of this book. Their contributions
have greatly improved its accuracy, readability, and value.
This book certainly would not have been possible without a lot of hard work and sup-
port from the skillful staff at O’Reilly & Associates, including Ellie Volckhausen and
Emma Colby, the cover designers, David Futato, the interior designer, Neil Walls,
who converted the files, Colleen Gorman, the copyeditor and production editor, Rob
Romano and Jessamyn Read, the illustrators, Sheryl Avruch and Ann Schirmer, who
provided quality control, and Tom Dinse, the indexer. Also, thanks to Tim O’Reilly
for taking time to go through this book and providing valuable feedback.
From Sanjay
My heartfelt thanks to my coauthor Alan for his outstanding technical skills, and for
his constant cooperation during the writing of this book. Special thanks to Jonathan
for not only editing this book, but also for providing me with remote access to his
Oracle9i database.
My adventure with Oracle started in the Tribology Workbench project at Tata Steel,
Jamshedpur, India. Sincere thanks to my co-workers in the Tribology Workbench
Preface | xiii
project for all the experiments and explorations we did during our learning days with
Oracle. Special thanks to Sarosh Muncherji, the Deputy Team Leader, for picking me
up for the project and then pushing me into the Oracle world by assigning me the
responsibility of being the DBA. Ever since, Oracle database technology has become
a way of life for me.
Sincere thanks to my co-workers at i2 Technologies for support and encouragement.
Last, but not the least, I thank my wife, Sudipti, for her support, understanding, and
constant encouragement.
From Alan
I would like to thank my coauthor Sanjay and my editor Jonathan Gennick for shar-
ing my vision for this book, and for their technical and editorial prowess. I would
never have reached the finish line without your help and encouragement.
Most of all, I would like to thank my wife, Nancy, for her support, patience, and
encouragement, and my daughters, Michelle and Nicole, for their love and inspiration.
xiv | Preface
Chapter 1 CHAPTER 1
Introduction to SQL
In this introductory chapter, we explore the origin and utility of the SQL language,
demonstrate some of the more useful features of the language, and define a simple
database design from which most examples in the book are derived.
What Is SQL?
SQL, which stands for Structured Query Language, is a special-purpose language
used to define, access, and manipulate data. SQL is nonprocedural, meaning that it
describes the necessary components (i.e., tables) and desired results without dictat-
ing exactly how results should be computed. Every SQL implementation sits atop a
database engine, whose job it is to interpret SQL statements and determine how the
various data structures in the database should be accessed in order to accurately and
efficiently produce the desired outcome.
The SQL language includes two distinct sets of commands: Data Definition Lan-
guage (DDL) is the subset of SQL used to define and modify various data structures,
while Data Manipulation Language (DML) is the subset of SQL used to access and
manipulate data contained within the data structures previously defined via DDL.
DDL includes numerous commands for handling such tasks as creating tables,
indexes, views, and constraints, while DML is comprised of just four statements:
INSERT
Adds data to a database.
UPDATE
Modifies data in a database.
DELETE
Removes data from a database.
SELECT
Retrieves data from a database.
Some people feel that DDL is the sole property of database administrators, while
database developers are responsible for writing DML statements, but the two are not
so easily separated. It is difficult to efficiently access and manipulate data without an
understanding of what data structures are available and how they are related; like-
wise, it is difficult to design appropriate data structures without knowledge of how
the data will be accessed. That being said, this book deals almost exclusively with
DML, except where DDL is presented in order to set the stage for one or more DML
examples. The reasons for focusing on just the DML portion of SQL include:
• DDL is well represented in various books on database design and administra-
tion as well as in SQL reference guides.
• Most database performance issues are the result of inefficient DML statements.
• Even with a paltry four statements, DML is a rich enough topic to warrant not
just one book, but a whole series of books.*
So why should you care about SQL? In this age of Internet computing and n-tier
architectures, does anyone even care about data access anymore? Actually, efficient
storage and retrieval of information is more important than ever:
• Many companies now offer services via the Internet. During peak hours, these
services may need to handle thousands of concurrent requests, and unaccept-
able response times equate to lost revenue. For such systems, every SQL state-
ment must be carefully crafted to ensure acceptable performance as data
volumes increase.
• We can store a lot more data today than we could five years ago. A single disk
array can hold tens of terabytes of data, and the ability to store hundreds of ter-
abytes is just around the corner. Software used to load or analyze data in these
environments must harness the full power of SQL in order to process ever-
increasing data volumes within constant (or shrinking) time windows.
Hopefully, you now have an appreciation for what SQL is and why it is important.
The next section will explore the origins of the SQL language and the support for the
SQL standard in Oracle’s products.
* Anyone who writes SQL in an Oracle environment should be armed with the following three books: a refer-
ence guide to the SQL language, such as Oracle SQL: The Essential Reference (O’Reilly), a performance-tun-
ing guide, such as Oracle SQL Tuning Pocket Reference (O’Reilly), and the book you are holding, which
shows how to best utilize and combine the various features of Oracle’s SQL implementation.
DSL/Alpha for manipulating data in a relational database. IBM liked what they saw,
so they commissioned a project called System/R to build a prototype based on
Codd’s work. Among other things, the System/R team developed a simplified ver-
sion of DSL called SQUARE, which was later renamed SEQUEL, and finally
renamed SQL.
The work done on System/R eventually led to the release of various IBM products
based on the relational model. Other companies, such as Oracle, rallied around the
relational flag as well. By the mid 1980’s, SQL had gathered sufficient momentum in
the marketplace to warrant oversight by the American National Standards Institute
(ANSI). ANSI released its first SQL standard in 1986, followed by updates in 1989,
1992, and 1999.
Thirty years after the System/R team began prototyping a relational database, SQL is
still going strong. While there have been numerous attempts to dethrone relational
databases in the marketplace, well-designed relational databases coupled with well-
written SQL statements continue to succeed in handling large, complex data sets
where other methods fail.
tuples). Instead, we use practical terms such as tables and rows, and we refer to the
various parts of an SQL statement by name rather than by function (i.e., “SELECT
clause” instead of projection). With all due respect to Dr. Codd, you will never
hear the word tuple used in a business setting, and, since this book is targeted
toward people who use Oracle products to solve business problems, you won’t
find it here either.
A Simple Database
Because this is a practical book, it contains numerous examples. Rather than fabri-
cating different sets of tables and columns for every chapter or section in the book,
we have decided to draw from a single, simple schema for most examples. The sub-
ject area that we chose to model is a parts distributor, such as an auto-parts whole-
saler or medical device distributor, in which the business fills customer orders for
one or more parts that are supplied by external suppliers. Figure 1-1 shows the
entity-relationship model for this business.
If you are unfamiliar with entity-relationship models, here is a brief description of
how they work. Each box in the model represents an entity, which correlates to a
database table.* The lines between the entities represents the relationships between
tables, which correlate to foreign keys. For example, the CUST_ORDER table holds
a foreign key to the employee table, which signifies the salesperson responsible for a
particular order. Physically, this means that the CUST_ORDER table contains a col-
umn holding employee ID numbers, and that, for any given order, the employee ID
number indicates the employee who sold that order. If you find this confusing, sim-
ply use the diagram as an illustration of the tables and columns found within our
database. As you work your way through the SQL examples in this book, return
occasionally to the diagram, and you should find that the relationships start mak-
ing sense.
DML Statements
In this section, we introduce the four statements that comprise the DML portion of
SQL. The information presented in this section should be enough to allow you to
start writing DML statements. As is discussed at the end of the section, however,
DML can look deceptively simple, so keep in mind while reading the section that
there are many more facets to DML than are discussed here.
* Depending on the purpose of the model, entities may or may not correlate to database tables. For example,
a logical model depicts business entities and their relationships, whereas a physical model illustrates tables
and their primary/foreign keys. The model in Figure 1-1 is a physical model.
SALESPERSON MONTHS
SALESPERSON_ID: NUMBERS(5) YEAR: NUMBER(4)
NAME: VARCHAR2(50) MONTH: NUMBER(2)
PRIMARY_REGION_ID: NUMBER(5)
ORDERS
YEAR: NUMBER(4)
MONTH: NUMBER(2) REGION
CUST_NBR: NUMBER(5)
REGION_ID: NUMBER(5) REGION_ID: NUMBER(5)
SALESPERSON_ID: NUMBERS(5) NAME: VARCHAR2(50) JOB
TOT_ORDERS: NUMBER(7) SUPER_REGION_ID: NUMBER(5)
TOT_SALES: NUMBER(11,2) JOB_ID: NUMBER(3)
FUNCTION: VARCHAR2(20)
Order warehouse
CUST_ORDER
CUSTOMER ORDER_NBR: NUMBER(5) EMPLOYEE
CUST_NBR: NUMBER(5) EMP_ID: NUMBER(5)
CUST_NBR: NUMBER(5)
NAME: VARCHAR2(30) SALES_EMP_ID: NUMBER(5) FNAME: VARCHAR2(20)
REGION_ID: NUMBER(5) SALE_PRICE: NUMBER(9,2) LNAME: VARCHAR(20)
INACTIVE_DT: DATE ORDER_DT: DATE DEPT_ID: NUMBER(5)
INACTIVE_IND: CHAR(1) EXPECTED_SHIP_DT: DATE SALARY: NUMBER(5)
TOT_ORDERS: NUMBER(5) CANCELLED_DATE: DATE HIRE_DATE: DATE
LAST_ORDER_DT: DATE SHIP_DT: DATE JOB_ID: : NUMBER(3)
STATUS: VARCHAR(20) MANAGER_EMP_ID: NUMBER(5)
PART
PART_NBR: VARCHAR2(20)
LINE_ITEM DEPARTMENT
NAME: VARCHAR(30) Dept_ID: NUMBER(5)
SUPPLIER_ID: NUMBER(5) ORDER_NBR: NUMBER(5)
STATUS: VARCHAR2(10) PART_NBR: NUMBER2(20) NAME: VARCHAR2(20)
INVENTORY_QTY: NUMBER(5) QTY: NUMBER(5) LOCATION_ID: NUMBER(3)
UNIT_COST: : NUMBER(8,2) FILLED_QTY: NUMBER(5)
RESUPPLY_DATE: DATE
DML Statements | 5
While the SELECT and FROM clauses are required, the WHERE clause is optional
(although you will seldom see it omitted). We therefore begin with a simple example
that retrieves three columns from every row of the customer table:
SELECT cust_nbr, name, region_id
FROM customer;
Our result set now includes only those customers residing in the region with a
region_id of 8. But what if we want to specify a region by name instead of region_id?
We could query the region table for a particular name and then query the customer
table using the retrieved region_id. Instead of issuing two different queries, however,
we could produce the same outcome using a single query by introducing a join, as in:
SELECT customer.cust_nbr, customer.name, region.name
FROM customer, region
WHERE region.name = 'New England'
AND region.region_id = customer.region_id;
Our FROM clause now contains two tables instead of one, and the WHERE clause
contains a join condition that specifies that the customer and region tables are to be
joined using the region_id column found in both tables. Joins and join conditions
will be explored in detail in Chapter 3.
Since both the customer and region tables contain a column called name, you must
specify which table’s name column you are interested in. This is done in the previ-
ous example by using dot-notation to append the table name in front of each col-
umn name. If you would rather not type the full table names, you can assign table
aliases to each table in the FROM clause and use those aliases instead of the table
names in the SELECT and WHERE clauses, as in:
SELECT c.cust_nbr, c.name, r.name
FROM customer c, region r
WHERE r.name = `New England'
AND r.region_id = c.region_id;
In this example, we assigned the alias “c” to the customer table and the alias “r” to
the region table. Thus, we can use “c.” and “r.” instead of “customer.” and “region.”
in the SELECT and WHERE clauses.
DML Statements | 7
While the first three items in this list are fairly straightforward, the last item merits
further discussion. Oracle makes available several phantom columns, known as
pseudocolumns, that do not exist in any tables. Rather, they are values visible during
query execution that can be helpful in certain situations.
For example, the pseudocolumn ROWID represents the physical location of a row.
This information represents the fastest possible access mechanism. It can be useful if
you plan to delete or update a row retrieved via a query. However, you should never
store ROWID values in the database, nor should you reference them outside of the
transaction in which they are retrieved, since a row’s ROWID can change in certain
situations, and ROWIDs can be reused after a row has been deleted.
The next example demonstrates each of the different elements from the previous list:
SELECT rownum,
cust_nbr,
1 multiplier,
'cust # ' || cust_nbr cust_nbr_str,
'hello' greeting,
TO_CHAR(last_order_dt, 'DD-MON-YYYY') last_order
FROM customer;
Interestingly, your SELECT clause is not required to reference columns from any of
the tables in the FROM clause. For example, the next query’s result set is composed
entirely of literals:
SELECT 1 num, 'abc' str
FROM customer;
NUM STR
---------- ---
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
1 abc
Since there are 30 rows in the customer table, the query’s result set includes 30 iden-
tical rows of data.
DML Statements | 9
You may also designate the sort column(s) by their position in the SELECT clause.
To sort the previous query by customer number, which is the first column in the
SELECT clause, you could issue the following statement:
SELECT c.cust_nbr, c.name, r.name
FROM customer c, region r
WHERE r.name = 'New England'
AND r.region_id = c.region_id
ORDER BY 1;
Specifying sort keys by position will certainly save you some typing, but it can often
lead to errors if you later change the order of the columns in your SELECT clause.
Removing duplicates
In some cases, your result set may contain duplicate data. For example, if you are
compiling a list of parts that were included in last month’s orders, the same part
number would appear multiple times if more than one order included that part. If
you want duplicates removed from your result set, you can include the DISTINCT
keyword in your SELECT clause, as in:
SELECT DISTINCT li.part_nbr
FROM cust_order co, line_item li
WHERE co.order_dt >= TO_DATE('01-JUL-2001','DD-MON-YYYY')
AND co.order_dt < TO_DATE('01-AUG-2001','DD-MON-YYYY')
AND co.order_nbr = li.order_nbr;
This query returns the distinct set of parts ordered during July of 2001. Without the
DISTINCT keyword, the result set would contain one row for every line-item of
every order, and the same part would appear multiple times if it was included in mul-
tiple orders. When deciding whether to include DISTINCT in your SELECT clause,
keep in mind that finding and removing duplicates necessitates a sort operation,
which can add quite a bit of overhead to your query.
The NOT NULL designation for the emp_id, lname, and dept_id columns indicates
that values are required for these three columns. Therefore, we must be sure to pro-
vide values for at least these three columns in our INSERT statements, as demon-
strated by the following:
INSERT INTO employee (emp_id, lname, dept_id)
VALUES (101, 'Smith', 2);
The VALUES clause must contain the same number of elements as the column list, and
the data types must match the column definitions. In the example, emp_id and dept_id
hold numeric values while lname holds character data, so our INSERT statement will
execute without error. Oracle always tries to convert data from one type to another
automatically, however, so the following statement will also run without errors:
INSERT INTO employee (emp_id, lname, dept_id)
VALUES ('101', 'Smith', '2');
Sometimes, the data to be inserted needs to be retrieved from one or more tables.
Since the SELECT statement generates a result set consisting of rows and columns of
data, you can feed the result set from a SELECT statement directly into an INSERT
statement, as in:
INSERT INTO employee (emp_id, fname, lname, dept_id, hire_date)
SELECT 101, 'Dave', 'Smith', d.dept_id, SYSDATE
FROM department d
WHERE d.name = 'Accounting';
* NULL indicates the absence of a value. The use of NULL will be studied in Chapter 2.
DML Statements | 11
In this example, the purpose of the SELECT statement is to retrieve the department
ID for the Accounting department. The other four columns in the SELECT clause are
supplied as literals.
In some cases, the values needed for one or more of the conditions in your WHERE
clause exist in another table. For example, your company may decide to outsource its
accounting functions, thereby necessitating the removal of all Accounting personnel
from the employee table:
DELETE FROM employee
WHERE dept_id =
(SELECT dept_id
FROM department
WHERE name = 'Accounting');
The use of the SELECT statement in this example is known as a subquery and will be
studied in detail in Chapter 5.
If you want to modify more than one column in the table, you have two choices: pro-
vide a set of column/value pairs separated by commas, or provide a set of columns
and a subquery. The following two UPDATE statements modify the inactive_dt and
inactive_ind columns in the customer table for any customer who hasn’t placed an
order in the past year:
UPDATE customer
SET inactive_dt = SYSDATE, inactive_ind = 'Y'
WHERE last_order_dt < SYSDATE — 365;
UPDATE customer
SET (inactive_dt, inactive_ind) =
(SELECT SYSDATE, 'Y' FROM dual)
WHERE last_order_dt < SYSDATE — 365;
The subquery in the second example is a bit forced, since it uses a query against the
dual* table to build a result set containing two literals, but it should give you an idea
of how you would use a subquery in an UPDATE statement. In later chapters, you
will see far more interesting uses for subqueries.
* Dual is an Oracle-provided table containing exactly one row with one column. It comes in handy when you
need to construct a query that returns exactly one row.
DML Statements | 13
Chapter
CHAPTER 2 2
Whether we are querying, modifying, or deleting data, the WHERE clause is the
mechanism for identifying the sets of data we want to work with. In this chapter, we
explore the role of the WHERE clause in SQL statements, as well as the various
options available when building a WHERE clause.
If the part table contains 10,000 items, the result set returned by the query would
consist of 10,000 rows, each with 5 columns. You would then load the 10,000 rows
into memory and make your modifications.
Once you have made the required modifications to your data in memory, it is time to
apply the changes to the part table. Without the ability to specify the rows to modify,
you have no choice but to delete all rows in the table and re-insert all 10,000 rows:
DELETE FROM part;
14
If 100 companies supply the 10,000 parts in the part table, this query will return
1,000,000 rows. Known as the Cartesian product, this number equates to every possi-
ble combination of all rows from the two tables. As you sift through the million
rows, you would keep only those where the values of p.supplier_id and s.supplier_id
are identical and where the s.name column matches 'Acme Industries'. If Acme
Industries supplies only 50 of the 10,000 parts in your database, you will end up dis-
carding 999,950 of the 1,000,000 rows returned by your query.
The WHERE clause here is comprised of two parts, known as conditions, which are
evaluated separately. Conditions always evaluate to either TRUE or FALSE; if there
are multiple conditions in a WHERE clause, they all must evaluate to TRUE in order
for a given row to be included in the result set.* For this example, a row created by
combining data from the part and supplier tables will only be included in the final
result set if both tables share a common value for the supplier_id column, and if the
value of the name column in the supplier tables matches 'Acme Industries'.† Any other
permutation of data from the two tables would evaluate to FALSE and be discarded.
With the addition of the WHERE clause to the previous example, therefore, Oracle
will take on the work of discarding undesired rows from the result set, and only 50
* This is an oversimplification. As you will see later, using the OR and NOT operators allows the WHERE
clause to evaluate to TRUE even if individual conditions evaluate to FALSE.
† Another oversimplification. The Oracle optimizer (the component tasked with finding the most efficient way
to execute a query) doesn’t first create every possible combination of rows from every table or view in the
FROM clause before it begins evaluating conditions. Rather, the optimizer chooses the order in which to
evaluate conditions and join data sets so execution time is (hopefully) minimized.
rows will be returned by the query, rather than 1,000,000. Now that you have
retrieved the 50 rows of interest from the database, you can begin the process of
modifying the data. Keep in mind, however, that with the WHERE clause at your
disposal you will no longer need to delete and re-insert your modified data; instead,
you can use the UPDATE statement to modify specific rows based on the part_nbr
column, which is the unique identifier for the table:
UPDATE part
SET status = 'DISCONTINUED'
WHERE part_nbr = 'AI5-4557';
The WHERE clause in this statement consists of a single condition that equates the
supplier_id column to the value returned by a query against the supplier table. A
query wrapped in parentheses inside another SQL statement is known as a subquery;
subqueries will be studied extensively in Chapter 5, so don’t worry if this looks a bit
intimidating. The net result is that the condition will be rewritten to use the value
returned by the subquery, as in:
UPDATE part
SET status = 'DISCONTINUED'
WHERE supplier_id = 1;
When executed, the condition evaluates to TRUE for exactly 50 of the 10,000 rows
in the part table, and the status of those 50 rows changes to DISCONTINUED.
The WHERE clause consists of two conditions separated by AND. Thus, a row will
only be included if both conditions evaluate to TRUE. Table 2-1 shows the possible
scenarios when conditions are replaced by their possible outcomes.
Using basic logic rules, we can see that the only combination of outcomes that
results in a final value of TRUE being assigned to a candidate row is where both con-
ditions evaluate to TRUE. Table 2-2 demonstrates the possible outcomes if our con-
ditions had been separated by OR rather then AND.
Next, let’s spice our query up a bit by including parts supplied by either Acme Indus-
tries or Tilton Enterprises:
SELECT p.part_nbr, p.name, p.supplier_id, p.status, p.inventory_qty,
s.supplier_id, s.name
FROM part p, supplier s
WHERE s.supplier_id = p.supplier_id
AND (s.name = 'Acme Industries'
OR s.name = 'Tilton Enterprises');
We now have three separate conditions separated by AND and OR with parentheses
surrounding two of the conditions. Table 2-3 illustrates the possible outcomes.
Since a particular part cannot be supplied by both Acme Industries and Tilton Enter-
prises, the intermediate results TRUE AND (TRUE AND TRUE) and FALSE AND
(TRUE AND TRUE) were not included in Table 2-3.
To liven things up even more, we can also throw in the NOT operator. The follow-
ing query returns data for parts supplied by anyone other than Acme Industries or
Tilton Enterprises:
SELECT p.part_nbr, p.name, p.supplier_id, p.status, p.inventory_qty,
s.supplier_id, s.name
FROM part p, supplier s
WHERE s.supplier_id = p.supplier_id
AND NOT (s.name = 'Acme Industries'
OR s.name = 'Tilton Enterprises');
Table 2-4 demonstrates how the addition of the NOT operator changes the outcome.
The use of the NOT operator in the previous example is a bit forced; we will see
more natural ways of expressing the same logic in later examples.
Equality/Inequality Conditions
Most of the conditions that we use when constructing a WHERE clause will be
equality conditions used to join data sets together or to isolate specific values. We
have already encountered these types of conditions numerous times in previous
examples, including:
s.supplier_id = p.supplier_id
While this is an improvement over the previous version, the next section shows an
even cleaner way to represent the same logic.
Membership Conditions
Along with determining whether two expressions are identical, it is often useful to
determine whether one expression can be found within a set of expressions. Using
the IN operator, you can build conditions that will evaluate to TRUE if a given
expression exists in a set of expressions:
s.name IN ('Acme Industries', 'Tilton Enterprises')
You may also add the NOT operator to determine whether an expression does not
exist in a set of expressions:
s.name NOT IN ('Acme Industries', 'Tilton Enterprises')
Most people prefer to use a single condition with IN or NOT IN instead of writing
multiple conditions using = or !=, so we will take one last stab at our Acme/Tilton
query:
SELECT p.part_nbr, p.name, p.supplier_id, p.status, p.inventory_qty,
s.supplier_id, s.name
FROM part p, supplier s
WHERE s.supplier_id = p.supplier_id
AND s.name NOT IN ('Acme Industries', 'Tilton Enterprises');
The subquery evaluates to a (potentially empty) set of order numbers. All orders
whose order number exists in that set are then modified by the UPDATE statement.
Range Conditions
If you are dealing with dates or numeric data, you may be interested in whether a value
falls within a specified range rather than whether it matches a specific value or exists in
a finite set. For such cases, you may use the BETWEEN…AND operator, as in:
DELETE FROM cust_order
WHERE order_dt BETWEEN '01-JUL-2001' AND '31-JUL-2001';
To determine whether a value lies outside a specific range, you can add the NOT
operator:
SELECT order_nbr, cust_nbr, sale_price
FROM cust_order
WHERE sale_price NOT BETWEEN 1000 AND 10000;
When using BETWEEN, make sure the first value is the lowest of the two values
provided. While “BETWEEN 1 AND 10” and “BETWEEN 10 AND 1” might seem
logically equivalent, specifying the higher value first guarantees that your condition
will always evaluate to FALSE.
Ranges may also be specified using the operators <, >, <=, and >=, although doing
so requires writing two conditions rather than one. The previous query could also be
expressed as:
SELECT order_nbr, cust_nbr, sale_price
FROM cust_order
WHERE sale_price < 1000 OR sale_price > 10000;
Matching Conditions
When dealing with character data, there are some situations where you are looking
for an exact string match, and others where a partial match is sufficient. For the lat-
ter case, you can use the LIKE operator along with one or more pattern-matching
characters, as in:
DELETE FROM part
WHERE part_nbr LIKE 'ABC%';
The pattern-matching character “%” matches strings of any length, so all of the fol-
lowing part numbers would be deleted: 'ABC', 'ABC-123', 'ABC9999999'. If you need
finer control, you can use the underscore (_) pattern-matching character to match
single characters, as in:
DELETE FROM part
WHERE part_nbr LIKE '_B_';
For this pattern, any part number with exactly 3 characters with a B in the middle
would be deleted. Both pattern-matching characters may be utilized in numerous
combinations to find the desired data. Additionally, the NOT operator may be
employed to find strings that don’t match a specified pattern. The following exam-
ple deletes all parts whose name does not contain a Z in the third position followed
later by the string “T1J”:
DELETE FROM part
WHERE part_nbr NOT LIKE '_ _Z%T1J%';
Oracle provides a slew of built-in functions for handling character data that can be
used to build matching conditions. For example, the condition part_nbr LIKE 'ABC%'
could be rewritten using the SUBSTR function as SUBSTR(part_nbr, 1, 3) = 'ABC'. For
definitions and examples for all of Oracle’s built-in functions, see Oracle SQL: The
Essential Reference (O’Reilly).
Handling NULL
The NULL expression represents the absence of a value. If, when entering an order
into the database, you are uncertain when the order will be shipped, it is better to
leave the ship date undefined than to fabricate a value. Until the ship date has been
determined, therefore, it is best to leave the ship_dt column NULL. NULL is also
useful for cases where data is not applicable. For example, a cancelled order’s ship-
ping date is no longer applicable and should be set to NULL.
When working with NULL, the concept of equality does not apply; a column may be
NULL, but it will never equal NULL. Therefore, you will need to use the special
operator IS when looking for NULL data, as in:
UPDATE cust_order
SET expected_ship_dt = SYSDATE + 1
WHERE ship_dt IS NULL;
In this example, all orders whose shipping date hasn’t been specified will have their
expected shipping date bumped forward by one day.
You may also use the NOT operator to locate non-NULL data:
UPDATE cust_order
SET expected_ship_dt = NULL
WHERE ship_dt IS NOT NULL;
This example sets the expected shipping date to NULL for all orders that have
already shipped. Notice that the SET clause uses the equality operator (=) with
NULL, whereas the WHERE clause uses the IS and NOT operators. The equality
operator is used to set a column to NULL, whereas the IS operator is used to evalu-
ate whether a column is NULL. A great many mistakes might have been avoided had
the designers of SQL chosen a special operator to be utilized when setting a column
to NULL (i.e., SET expected_ship_dt TO NULL), but this is not the case. To make
matters worse, Oracle doesn’t complain if you mistakenly use the equality operator
when evaluating for NULL. The following query will parse and execute but will
never return rows:
SELECT order_nbr, cust_nbr, sale_price, order_dt
FROM cust_order
WHERE ship_dt = NULL;
Hopefully, you would quickly recognize that the previous query never returns data
and replace the equality operator with IS. However, there is a more subtle mistake
involving NULL that is harder to spot. Say you are looking for all employees who are
not managed by Jeff Blake, whose employee ID is 11. Your first instinct may be to
run the following query:
While this query returns rows, it leaves out those employees who are top-level man-
agers and, thus, are not managed by anyone. Since NULL is neither equal to 11 nor
not equal to 11, this set of employees is absent from the result set. In order to ensure
that all employees are considered, you will need to explicitly handle NULL, as in:
SELECT fname, lname, manager_emp_id
FROM employee
WHERE manager_emp_id IS NULL OR manager_emp_id != 11;
Including two conditions for every nullable column in your WHERE clause can get a
bit tiresome. Instead, you can use Oracle’s built-in function NVL, which substitutes
a specified value for columns that are NULL, as in:
SELECT fname, lname, manager_emp_id
FROM employee
WHERE NVL(manager_emp_id, -999) != 11;
In this example, the value -999 is substituted for all NULL values, which, since -999
is never equal to 11, guarantees that all rows whose manager_emp_id column is
NULL will be included in the result set. Thus, all employees whose manager_emp_id
column is NULL or is not NULL and has a value other than 11 will be retrieved by
the query.
5. When using OR, put the condition requiring the least effort to evaluate first. If
the first condition evaluates to TRUE, Oracle won’t bother evaluating the
remaining OR’d conditions, possibly saving significant execution time. This
strategy is useful with correlated subqueries, which are generally executed once
per candidate row.
6. Handle NULLs properly. After writing your WHERE clause, inspect each condi-
tion with respect to its ability to properly handle NULL values. Take the time to
understand the table definitions in your database so that you know which col-
umns allow NULLs.
7. Pick up introductory books on logic and set theory at your local library. While
understanding these two topics won’t necessarily get you invited to more cock-
tail parties, it will certainly make you a better SQL programmer.
Chapter
CHAPTER 3 3
Joins
Most of the things in life are not self-contained. There is not one shop where you will
find all your requirements. This is valid for database tables as well. Quite often, you
need information from more than one table. The SQL construct that combines data
from two or more tables is called a join. This chapter takes you into the details of
joins, their types, and their usage.
A join is a SQL query that extracts information from two or more tables or views.
When you specify multiple tables or views in the FROM clause of a query, Oracle
performs a join, linking rows from multiple tables together. There are several types of
joins to be aware of:
Inner joins
Inner joins are the regular joins. An inner join returns the rows that satisfy the
join condition. Each row returned by an inner join contains data from all tables
involved in the join.
Outer joins
Outer joins are an extension to the inner joins. An outer join returns the rows
that satisfy the join condition and also the rows from one table for which no cor-
responding rows (i.e., that satisfy the join condition) exist in the other table.
Self joins
A self join is a join of a table to itself.
The following sections discuss each of these joins with examples.
Inner Joins
An inner join returns the rows that satisfy the join condition. Let’s take an example
to understand the concept of a join. Say you want to list the name and department
name for each employee. To do this, you would use the following SQL statement:
SELECT E.LNAME, D.NAME
FROM EMPLOYEE E, DEPARTMENT D
26
LNAME NAME
---------- --------------
SMITH RESEARCH
ALLEN SALES
WARD SALES
JONES RESEARCH
MARTIN SALES
BLAKE SALES
CLARK ACCOUNTING
SCOTT RESEARCH
KING ACCOUNTING
TURNER SALES
ADAMS RESEARCH
JAMES SALES
FORD RESEARCH
MILLER ACCOUNTING
14 rows selected.
This example queries two tables, because the employee name is stored in the
EMPLOYEE table, whereas the department name is stored in the DEPARTMENT
table. Notice that the FROM clause lists two tables EMPLOYEE and DEPART-
MENT, separated by a comma (,). If you need to join three or more tables, you have
to specify all the tables in the FROM clause separated by commas. The SELECT list
may include columns from any of the tables specified in the FROM clause.
Note the use of table aliases in this query. It is common practice to use table aliases
while selecting data from multiple tables. Whenever there is an ambiguity in the col-
umn names, you must use a table alias (or the table name) to qualify any ambiguous
column names. For example, the column name DEPT_ID appears in both the tables.
Therefore, the table aliases E and D are used in the WHERE clause to ask Oracle to
equate DEPT_ID column from EMPLOYEE table with the DEPT_ID column from
the DEPARTMENT table. Note that the table aliases have been used with the col-
umns in the SELECT clause as well, even though the column names are unambigu-
ous. It is good practice to use table aliases everywhere in a query if you are using
them at all.
Cartesian Product
If you don’t specify the join condition while joining two tables, Oracle combines each
row from the first table with each row of the second table. This type of result set is
called as a Cartesian product. The number of rows in a Cartesian product is the prod-
uct of the number of rows in each table. Here’s an example of a Cartesian product:
SELECT E.LNAME, D.NAME
FROM EMPLOYEE E, DEPARTMENT D;
Inner Joins | 27
LNAME NAME
---------- --------------
SMITH ACCOUNTING
ALLEN ACCOUNTING
WARD ACCOUNTING
JONES ACCOUNTING
MARTIN ACCOUNTING
BLAKE ACCOUNTING
...
...
...
SCOTT OPERATIONS
KING OPERATIONS
TURNER OPERATIONS
ADAMS OPERATIONS
JAMES OPERATIONS
FORD OPERATIONS
MILLER OPERATIONS
56 rows selected.
Note that since the query didn’t specify a join condition, each row from the
EMPLOYEE table is combined with each row from the DEPARTMENT table. Need-
less to say, this result set is of little use. More often than not a Cartesian product pro-
duces a result set containing misleading rows. Therefore, unless you are sure that
you want a Cartesian product, don’t forget to include the join condition when you
specify more than one table in the FROM clause.
Join Condition
Usually when you perform a join, you specify a condition in the WHERE clause that
relates the tables specified in the FROM clause. This condition is referred to as the
join condition. The join condition specifies how the rows from one table will be com-
bined with the rows of another table. Usually, the join condition is applied to the for-
eign key columns. In the first example in the previous section, the WHERE clause
specifies the join condition by which the DEPT_ID column of the EMPLOYEE table
is equated with the DEPT_ID column of the DEPARTMENT table:
WHERE E.DEPT_ID = D.DEPT_ID
To perform the join, Oracle picks up one combination of rows from the two tables,
and checks to see whether the join condition is true. If the join condition is true,
Oracle includes this combination of rows in the result set. The process is repeated for
all combinations of rows from the two tables. Some of the things that you should
know about the join condition are discussed in the following list.
• The columns specified in the join condition need not be specified in the SELECT
list. In the following example, the join condition involves the DEPT_ID column
from the EMPLOYEE and DEPARTMENT tables; however, the DEPT_ID col-
umn is not selected:
28 | Chapter 3: Joins
However, there are situations in which you need non-equi-joins to get the required
information. For example, if you want to list the INVENTORY_CLASS of each
PART, you need to execute the following query:
SELECT P.NAME PART_NAME, C.CLASS INV_CLASS
FROM PART P, INVENTORY_CLASS C
WHERE P.UNIT_COST BETWEEN C.LOW_COST AND C.HIGH_COST;
Note the use of the BETWEEN operator while relating the UNIT_COST column
from the PART table with the LOW_COST and HIGH_COST columns of the
INVENTORY_CLASS table.
Inner Joins | 29
Outer Joins
Sometimes while performing a join between two tables, you need to return all the
rows from one table even when there are no corresponding rows in the other table.
Consider the following two tables, SUPPLIER and PART:
SELECT * FROM SUPPLIER;
SUPPLIER_ID NAME
----------- ------------------------------
101 Pacific Disks, Inc.
102 Silicon Valley MicroChips
103 Blue River Electronics
If you want to list all the suppliers and all the parts supplied by them, it is natural to
use the following query:
SELECT S.SUPPLIER_ID, S.NAME SUPPLIER_NAME, P.PART_NBR, P.NAME PART_NAME
FROM SUPPLIER S, PART P
WHERE S.SUPPLIER_ID = P.SUPPLIER_ID;
Note that even though we have three suppliers, this query lists only two of them,
because the third supplier (Blue River Electronics) doesn’t currently supply any part.
When Oracle performs the join between SUPPLIER table and PART table, it matches
the SUPPLIER_ID from these two tables (as specified by the join condition). Since
SUPPLIER_ID 103 doesn’t have any corresponding record in the PART table, that
supplier is not included in the result set. This type of join is the most natural, and is
known as an inner join.
However, we want to see all the suppliers even if they don’t supply any parts. Oracle
provides a special type of join to include rows from one table that don’t have matching
30 | Chapter 3: Joins
É
— Étourdi ou non, tu es comme toujours trois fois le bienvenu,
répondit M. de Preymont d’un ton affectueux.
Leur amitié remontait au collège. Lorsque l’enfant difforme et
timide s’était trouvé livré sans défense à la persécution traditionnelle
de ses camarades, Saverne, quoique sensiblement plus jeune que
lui, l’avait pris sous sa protection, et, pendant que ses poings
robustes mettaient la paix, son bon cœur avait de chaudes paroles
pour consoler Preymont, qui ne devait pas plus oublier cette
intervention bienfaisante que la profonde amertume de ces jours
passés.
Une solide amitié se cimenta entre eux, et, plus tard, les rôles
furent intervertis, car Saverne, à peine eut-il la bride sur le cou,
s’empressa de dévorer son patrimoine, et Preymont, tout en
essayant de calmer sa fougue par de bons conseils, le tira plus d’une
fois d’un mauvais pas en lui prêtant sa bourse. Ses conseils, écoutés
et approuvés avec enthousiasme, glissaient sur une nature
excellente, facile à l’entraînement, s’abandonnant aux caprices du
moment avec l’insouciance d’un esprit dont les principes sont
élastiques et dont la liberté n’est entravée par aucun lien de famille.
Mais Saverne avait le don rare de plaire à tout le monde ; les gens
les plus sérieux lui pardonnaient les écarts de sa nature superficielle
en faveur de sa bonne humeur inaltérable, de la franchise avec
laquelle il avouait ses torts et d’une verve qui entraînait les rieurs de
son côté.
Mme de Preymont le traitait en enfant très aimé pour lequel on a
des indulgences inépuisables, et Saverne, sans intérieur, sans
famille, considérait comme sienne la maison de son ami. Il vivait
largement du produit de ses talents. Caricaturiste recherché, il
écrivait en outre d’une plume légère et facile dans différentes feuilles
périodiques.
— Eh bien, enfant terrible, lui dit Mme de Preymont, quelles
sottises avez-vous faites depuis que je vous ai vu ?
Saverne, qui dégustait des fraises, cessa de manger pour
réfléchir sérieusement, et s’écria d’un air étonné :
— Aucune !… Par le ciel, madame, c’est étonnant !
— Alors vous nous revenez tout à fait converti. La dernière fois
que nous avons causé ensemble, vous parliez de mariage avec une
grande sagesse.
— Ah ! ma sagesse est plus grande que jamais, je ne demande
qu’à la suivre, mais…
Il jeta un regard éploré à Marc.
— Mais ta sagesse ne s’accorde pas avec celle… de tout le
monde, répondit Preymont en souriant.
— Tu l’as dit, répliqua Didier piteusement. Et pourtant je suis
fatigué de vivre seul… du moins sans intérieur régu… bref, tu
comprends ! ajouta-t-il en noyant l’explication dans son café et le
respect que lui inspirait Mme de Preymont.
— J’aime à vous voir cet air soucieux, lui dit-elle, nous en
reparlerons, et je ferai en sorte de vous découvrir une sage petite
femme.
— Une sage petite femme ! répéta Saverne d’un ton inquiet.
Sage… oui, mais pas trop sérieuse, n’est-ce pas ? Je ne veux pas
d’une vertu coiffée d’un bonnet de coton ! s’écria-t-il avec effroi.
— Rassurez-vous, répondit Mme de Preymont en riant. Ce n’est
pas de nos jours que la vertu est tentée de mettre cette coiffure à la
mode.
Preymont conduisit son ami dans une chambre dont les vastes
proportions plaisaient à Saverne.
— Les femmes comme ta mère sont des femmes admirables,
déclara Didier, mettant en une minute le désordre autour de lui.
Admirables ! il n’y a pas d’autre expression. Seulement ces saintes,
entortillées de vertus et de bonnes pensées, ne connaissent pas plus
la vie qu’un enfant, et ne se doutent pas de l’embarras dans lequel
est plongé un pauvre garçon rempli de bon vouloir, mais orné d’un
crampon.
— Peut-être que si… mais je ne crois pas que ton malheur lui
inspire une profonde commisération.
— Voilà, voilà ! qu’est-ce que je disais ? s’écria Saverne en
bouleversant son sac de voyage pour chercher, sans la trouver, la
clef de sa malle. Elle croit qu’il est facile de vivre dans une cellule,
un capuchon sur le chef, une tête de mort devant soi pour méditer
et une cruche d’eau pour se restaurer… Mais bah ! je ne veux penser
à rien ce soir. Tout s’arrangera : mon crampon s’en ira au diable, et
je prierai ta mère de me trouver une femme, car, après tout, je dois
avouer qu’elle ne m’a jamais parlé de cellule, et que j’ai confiance en
son jugement.
Impatienté de ne pas trouver la clef qu’il cherchait, il fit sauter la
serrure de sa malle et en éparpilla le contenu autour de lui.
— Voilà qui est fait, dit-il avec satisfaction. Ton valet de chambre
se débrouillera demain avec mes effets. Une nuit passée à l’air leur
fera du bien, car c’est moi qui les ai fourrés là dedans, et je n’ai
jamais la patience de les arranger avec symétrie.
— Quand tu seras marié, ta malle ne ressemblera plus à une
hotte de chiffonnier, répondit Preymont en riant. Bonsoir !
Au moment d’ouvrir la porte, il se retourna pour dire avec effort :
— A propos de mariage… tu arrives précisément pour assister à
celui d’une cousine à moi.
— Ah !… est-ce la petite Suzanne que j’ai vue ici autrefois ?
— Oui… c’est Mlle Jeuffroy.
— Enfant, elle était gentille. Qu’est-elle devenue comme femme ?
— Tu la verras après-demain, c’est le jour du contrat, et je te
ferai inviter.
— Bravo ! j’étudierai sur le fiancé quelle tête il faut avoir quand
on se marie, et je trouverai bien parmi les invités quelques
silhouettes pour mon crayon.
Preymont, après une journée d’efforts pour se dominer, éprouvait
un impérieux besoin de solitude. Il sortit, puis traversa la route et les
prés qui séparaient la propriété des bords de la Loire.
Souvent, dans le même endroit, il était venu, fatigué d’un travail
aride ou saisi de tristesse devant des désirs irréalisables, chercher
dans l’imposant silence et la tranquille limpidité de la nuit le calme
extérieur qui agit sur la pensée. Mais alors il ne trouva dans la
solitude qu’un homme malheureux.
« J’aime…, pensait-il, moi qui n’ai même pas le droit, sans être
ridicule, d’associer ce mot à mes pensées. »
Et il se sentait aux prises avec des accès de misanthropie, de
colère, de découragement que son orgueil et sa philosophie étaient
impuissants à vaincre.
La réflexion, l’expérience et une tendance à la spéculation
avaient développé une largeur de pensée innée chez lui. Il aimait à
généraliser ses idées dans la contemplation de la place infime que,
pris isolément, l’homme occupe dans l’univers. Le regard posé sur le
renouvellement de la nature et des siècles, les lignes avaient alors à
ses yeux leurs proportions réelles, et il aimait à trouver ainsi une
liberté de jugement qui aurait détruit en lui les préjugés s’il en avait
eu. Il était résulté de cette tendance d’esprit que non seulement il
restait étranger aux vanités mesquines et aux intolérances étroites,
mais qu’il s’était créé une sorte de stoïcisme, à l’aide duquel il
prétendait s’élever au-dessus des faiblesses de l’amour-propre et de
la passion.
Mais, malgré ses affirmations, il y avait manque d’équilibre entre
ses sensations, ses sentiments et sa pensée. Il le voyait quand il se
laissait entraîner, parce qu’il souffrait, à des emportements
misanthropiques, malgré l’indulgence, malgré la profonde pitié qu’il
puisait pour l’humanité dans une intelligence saine et large.
Quand il remonta chez lui, la vie calmée de la nature endormie
n’avait fait qu’assister aux luttes d’un cœur ardent et comprimé,
plein d’une passion qui le livrait à une profonde angoisse.
III
Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.
ebookultra.com