Finally, the DBMS uses the value returned by the SET subquery to update the appropriate rows in the table titles.. ■ If you want to be extra-careful before you update rows, you can test
Trang 1Suppose that Abatis Publishers (publisher P01)
swallows Tenterhooks Press (P04) in a merger,
so now, all the Tenterhooks Press books are
published by Abatis Publishers Listing 10.13
works in a bottom-up fashion to change the
publisher IDs in titlesfrom P04 to P01
TheWHEREsubquery retrieves the pub_idfor
Tenterhooks Press The DBMS uses this pub_id
to retrieve the books in the table titleswhose
publisher is Tenterhooks Press Finally, the
DBMS uses the value returned by the SET
subquery to update the appropriate rows in
the table titles Because the subqueries are
used with an unmodified comparison
opera-tor, they must be scalar subqueries that return
a single value (that is, a one-row, one-column
result); see “Comparing a Subquery Value by
Using a Comparison Operator” in Chapter 8
Listing 10.13 updates five rows; see Figure
10.10 for the result
Figure 10.10 shows the table titlesafter
Listings 10.8 through 10.13 are run Each
listing updates values in a different column
(or columns) from those in the other
list-ings The updated values in each column are
shown in red
Listing 10.13 Change the publisher of all of
Tenterhooks Press’s books to Abatis Publishers See Figure 10.10 for the result.
UPDATE titles SET pub_id = (SELECT pub_id FROM publishers WHERE pub_name = 'Abatis Publishers') WHERE pub_id =
(SELECT pub_id FROM publishers WHERE pub_name = 'Tenterhooks Press');
Listing
title_id title_name type pub_id pages price sales pubdate contract - - - - - - -T01 1977! history P01 107 43.98 566 2003-01-01 0
T02 200 Years of German Humor history P03 14 39.90 9566 2003-01-01 0
T03 Ask Your System Administrator computer P02 1226 39.95 25667 2000-09-01 0
T04 But I Did It Unconsciously self help P01 NULL 12.99 13001 1999-05-31 0
T05 Exchange of Platitudes self help P01 NULL 6.95 100720 2001-01-01 0
T06 How About Never? biography P01 473 19.95 11320 2000-07-31 0
Trang 2✔ Tips
■ A DBMS will evaluate expressions in a
SETorWHEREclause by using the values
that the referenced columns had before
any updates Consider this UPDATE
statement:
UPDATE mytable
SET col1 = col1 * 2,
col2 = col1 * 4,
col3 = col2 * 8
WHERE col1 = 1
AND col2 = 2;
For the rows matching the WHERE
condi-tions, the DBMS sets col1to 2, col2to 4
(1✕4, not 2 ✕4), and col3to 16 (2 ✕8,
not 4 ✕8)
This evaluation scheme lets you swap
the values of compatible columns with:
UPDATE mytable
SET col1 = col2,
col2 = col1;
(This trick won’t work in MySQL.)
■ If you want to be extra-careful before you
update rows, you can test your UPDATE
statement on a temporary copy of the
target table; see “Creating a Temporary
Table with CREATE TEMPORARY TABLE” and
“Creating a New Table from an Existing
One with CREATE TABLE AS” in Chapter 11
■ You also canUPDATErows through a view;
see “Updating Data Through a View” in
Chapter 13
■ If you’re using transactions, you must use a COMMITstatement after your final
UPDATEstatement to make the changes
to the table permanent For information about transactions, see Chapter 14
■ SQL:2003 introduced the MERGE state-ment as a convenient way to combine multiple UPDATEandINSERToperations
in a single statement These operations
informally are called upserts Oracle and
DB2 support MERGE MySQL has the
sim-plifiedMERGEvariants REPLACE INTOand
INSERT ON DUPLICATE KEY UPDATE
■ In Microsoft Access date
liter-als, omit the DATEkeyword and surround the literal with # characters instead of quotes To run Listing 10.12, change the date literal to #2003-01-01#
Microsoft Access doesn’t support scalar
subqueries in the SETclause To run Listing 10.13, split the UPDATEstatement into two statements: one that SELECTs the pub_idfor Abatis Publishers from
publishersand one that uses this
pub_idto change the pub_idof all the Tenterhooks Press books in titles Then run the statements programmatically (in a host language such as Visual Basic
or C#), using the result of the first state-ment as the input for the second statestate-ment
continues on next page
Trang 3In Microsoft SQL Server and DB2 date
literals, omit the DATEkeyword To run Listing 10.12, change the date literal to
‘2003-01-01’
MySQL 4.1 and later support subqueries
but won’t run Listing 10.11 because MySQL won’t let you use the same table (titles, in this case) for both the sub-query’s FROMclause and the update target Earlier MySQL versions don’t support subqueries and won’t run Listings 10.11, 10.12, and 10.13; for workarounds, see the DBMS Tip in “Understanding Subqueries”
in Chapter 8
For MySQL, see also the DBMS Tip in
“Inserting Rows with INSERT” earlier in this chapter
To run Listings 10.9 and 10.11 in older
PostgreSQL versions, convert the
floating-point numbers to DECIMAL(see “Converting Data Types with CAST()” in Chapter 5) The changes are (Listing 10.9):
CAST(2.0 AS DECIMAL)
and (Listing 10.11):
CAST(0.5 AS DECIMAL)
For all DBMSs, check the
documenta-tion to see how your DBMS handles updating values in columns whose data type generates a unique row identifier automatically (see “Unique Identifiers”
in Chapter 3)
Trang 4Deleting Rows with DELETE
TheDELETEstatement removes rows from
a table You can use DELETEto remove:
◆ All rows in a table
◆ Specific rows in a table
To delete rows, you specify:
◆ The table whose rows to delete
◆ An optional search condition that
speci-fies which rows to delete
The important characteristics of DELETEare:
◆ Unlike INSERTandUPDATE,DELETEtakes
no column names because it removes
entire rows
◆ DELETEremoves rows from a table, but it
never deletes the table’s definition Even
if you remove all rows from a table, the
table itself still exists If you want to
delete a table definition (and all its
asso-ciated data, indexes, and so on), see
“Dropping a Table with DROP TABLE” in
Chapter 11
◆ DELETEtakes an optional WHEREclause
that specifies which rows to delete
Without a WHEREclause, DELETEremoves
all the rows in the table.
◆ DELETEis dangerous because it’s easy to omit the WHEREclause mistakenly (and remove all rows) or misspecify the WHERE
search condition (and remove the wrong rows) It’s wise to run a SELECTstatement that uses the same WHEREclause before running the actual DELETEstatement
Use SELECT *to display all rows that the DBMS will remove when you run DELETE,
or use SELECT COUNT(*)to display only the number of rows that will disappear
◆ To preserve referential integrity, you can define the action the DBMS takes auto-matically when you try to DELETEa key value to which foreign-key values point;
see the Tips in “Specifying a Foreign Key with FOREIGN KEY” in Chapter 11
◆ No expression can cause an arithmetic error (an overflow or divide-by-zero error, for example)
◆ Recall from “Tables, Columns, and Rows”
in Chapter 2 that the order of rows in a table is unimportant and that you have
no control over the physical location of rows, so a deletion might reorder the posi-tions of the rows remaining in a table
Trang 5To delete rows:
◆ Type:
DELETE FROM table
[WHERE search_condition];
table is the name of a table to delete
rows from
search_condition specifies the conditions
to be met for the rows that are deleted
The search_condition conditions can
be WHEREconditions (comparison
opera-tors,LIKE,BETWEEN,IN, and IS NULL; see
Chapter 4) or subquery conditions
(com-parison operators, IN,ALL,ANY, and
EXISTS; see Chapter 8), combined with
AND,OR, and NOT If the WHEREclause is
omitted, every row in table is deleted.
In the following examples, I’m going to
ignore referential-integrity constraints—
which I wouldn’t do in a production
data-base, of course
Listing 10.14 deletes every row in
royalties The lack of a WHEREclause tells
the DBMS to delete all the rows This
state-ment deletes 13 rows; see Figure 10.11 for
the result
TheWHEREclause in Listing 10.15 tells
the DBMS to remove the authors with the
last name Hull from authors This statement
deletes two rows; see Figure 10.12 for
the result
Listing 10.14 Delete all rows from the table royalties See Figure 10.11 for the result.
DELETE FROM royalties;
Listing
title_id advance royalty_rate - -
-Figure 10.11 Result of Listing 10.14.
Listing 10.15 Delete the rows in which the author’s
last name is Hull from the table authors See Figure 10.12 for the result.
DELETE FROM authors WHERE au_lname = 'Hull';
Listing
Trang 6You can delete rows in a given table based
on the values stored in another table
Listing 10.16 uses a subquery to remove all
the books published by publishers P01 or P04 fromtitle_authors This statement deletes
12 rows; see Figure 10.13 for the result.
✔ Tips
■ If you want to be extra-careful before you remove rows, you can test your DELETE
statement on a temporary copy of the target table; see “Creating a Temporary Table with CREATE TEMPORARY TABLE” and
“Creating a New Table from an Existing One with CREATE TABLE AS” in Chapter 11
■ You also canDELETErows through a view; see “Updating Data Through a View” in Chapter 13
■ If you’re using transactions, you must use a COMMITstatement after your final
DELETEstatement to make the changes
to the table permanent For information about transactions, see Chapter 14
Listing 10.16 Delete the rows for books published by
publisher P01 or P04 from the table title_authors
See Figure 10.13 for the result.
DELETE FROM title_authors
WHERE title_id IN
(SELECT title_id
FROM titles
WHERE pub_id IN ('P01', 'P04'));
Listing
title_id au_id au_order royalty_share
- - -
-T02 A01 1 1.00
T03 A05 1 1.00
T07 A02 1 0.50
T07 A04 2 0.50
T13 A01 1 1.00
Figure 10.13 Result of Listing 10.16.
Trang 7■ You can use a NOT EXISTSorNOT IN
sub-query to delete rows from one table that
refer to nonexistent rows in another
table (useful for removing orphaned rows
or referential-integrity violations) The
following statements remove all rows
from the table titlesfor which no
pub-lisher exists in the table publishers:
DELETE FROM titles
WHERE NOT EXISTS
(SELECT * FROM publishers
WHERE publishers.pub_id = titles.pub_id);
or
DELETE FROM titles
WHERE pub_id NOT IN
(SELECT pub_id FROM publishers);
■ In some DBMSs, the FROM
key-word is optional in a DELETE
statement, but you should always include
it for portability
MySQL 4.1 and later support subqueries
and will run Listing 10.16 Earlier MySQL
versions don’t support subqueries and
won’t run it; for workarounds, see the
DBMS Tip in “Understanding Subqueries”
in Chapter 8
For MySQL, see also the DBMS Tip in
“Inserting Rows with INSERT” earlier in
this chapter
Truncating Tables
If you want to delete all the rows in a table, the TRUNCATE statement is faster than
DELETE.TRUNCATEisn’t part of the SQL ,
standard, but Microsoft SQL Server,
Oracle, MySQL, and PostgreSQL
sup-port it.TRUNCATEworks like a DELETE
statement with no WHEREclause: Both remove all rows in a table But TRUNCATEis faster and uses fewer system resources than DELETEbecause TRUNCATEdoesn’t scan the entire table and record changes
in the transaction log (see Chapter 14) The trade-off is that with TRUNCATE, you can’t recover (roll back) your changes if you make a mistake The syntax is:
TRUNCATE TABLE table;
Trang 8Many DBMSs have interactive, graphical tools that let you create and manage tables and table properties such as column defini-tions and constraints This chapter explains how to perform those tasks programmatically
by using SQL:
◆ TheCREATE TABLEstatement creates a new table
◆ TheALTER TABLEstatement modifies the structure of an existing table
◆ TheDROP TABLEstatement destroys a table and all its data
◆ TheCREATE TEMPORARY TABLEstatement creates a table that the DBMS destroys automatically when it’s no longer in use
◆ TheCREATE TABLE ASstatement creates a new table from an existing one
These statements don’t return a result, but your DBMS might print a message indicat-ing whether the statement ran successfully
To see the actual effect the statement had
on a table, examine the table’s structure by using one of the commands described in
“Displaying Table Definitions” in Chapter 10 These statements modify database objects and data, so your database administrator might need to grant you permission to run them
Creating,
Altering, and
Dropping Tables
11
Trang 9Creating Tables
Database designers spend considerable time
normalizing tables and defining relationships
and constraints before they write a line of
SQL code If you’re going to create tables
for production databases, study database
design and relational-model principles
beyond those presented in Chapter 2
Recall from “Tables, Columns, and Rows”
in Chapter 2 that a database is organized
around tables To a user or an SQL
program-mer, a database appears to be a collection of
one or more tables (and nothing but tables)
To create a table, you specify the following:
◆ Table name
◆ Column names
◆ Data types of the columns
◆ Default values of columns
◆ Constraints
The table name and the column names
must conform to the rules for SQL
identi-fiers; see “Identifiers” in Chapter 3 The data
type of each column is a character, numeric,
datetime, or other data type; see “Data
Types” in Chapter 3 A default is the value
the column takes if you don’t specify a value
explicitly Constraints define properties such
as nullability, keys, and permissible values
You create a new table by using the CREATE TABLEstatement, whose general syntax is:
CREATE TABLE table
(
column1 data_type1 [col_constraints1], column2 data_type2 [col_constraints2],
columnN data_typeN [col_constraintsN]
[, table_constraint1]
[, table_constraint2]
[, table_constraintM]
);
Each column definition has a column name,
a data type, and an optional list of one or more column constraints An optional list
of table constraints follows the final column definition By convention, I start each col-umn definition and table constraint on its own line
Trang 10Understanding Constraints
Constraints let you define rules for values
allowed in columns (Table 11.1) Your DBMS
uses these rules to enforce the integrity of information in the database automatically
Constraints come in two flavors:
◆ A column constraint is part of a column
definition and imposes a condition on that column only
◆ A table constraint is declared
independ-ently of a column definition and can impose a condition on more than one column in a table You must use a table constraint to include more than one column in a single constraint
You can specify some constraints as either column or table constraints, depending on the context in which they’re used If a pri-mary key contains one column, for example, you can define it as either a column con-straint or a table concon-straint If the primary key has two or more columns, you must use
a table constraint
Assigning names to constraints lets you manage them efficiently; you can change or delete a named constraint by using the ALTER TABLEstatement, for example Constraint names are optional, but many SQL pro-grammers and database designers name
all constraints It’s not uncommon to leave
aNOT NULLconstraint unnamed, but you always should name other types of con-straints (even if I don’t do so in some of the examples)
Table 11.1
Constraints
C o n s t r a i n t D e s c r i p t i o n
NOT NULL Prevents nulls from being inserted into
a column
PRIMARY KEY Sets the table’s primary-key column(s)
FOREIGN KEY Sets the table’s foreign-key column(s)
UNIQUE Prevents duplicate values from being
inserted into a column
CHECK Limits the values that can be inserted
into a column by using logical
(Boolean) expressions