Suppose 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 titles from P04 to P01. The WHERE subquery retrieves the pub_id for Tenterhooks Press. The DBMS uses this pub_id to retrieve the books in the table titles whose 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 titles after 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. 330 Chapter 10 Updating Rows with UPDATE 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 T07 I Blame My Mother biography P03 333 23.95 750100 1999-10-01 0 T08 Just Wait Until After School children P01 86 10.00 4095 2001-06-01 0 T09 Kiss My Boo-Boo children P01 22 13.95 5000 2002-05-31 0 T10 Not Without My Faberge Egg biography P01 NULL NULL NULL NULL 0 T11 Perhaps It's a Glandular Problem self help P01 NULL 7.99 94123 2000-11-30 0 T12 Spontaneous, Not Annoying biography P01 507 12.99 100001 2000-08-31 0 T13 What Are The Civilian Applications? history P03 802 59.98 10467 2003-01-01 0 Figure 10.10 The table titles after I run Listings 10.8 through 10.13. The updated values are shown in red. ✔ Tips ■ A DBMS will evaluate expressions in a SET or WHERE clause 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 col1 to 2, col2 to 4 (1 ✕ 4, not 2 ✕ 4), and col3 to 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 can UPDATE rows through a view; see “Updating Data Through a View” in Chapter 13. ■ If you’re using transactions, you must use a COMMIT statement after your final UPDATE statement 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 UPDATE and INSERT operations in a single statement. These operations informally are called upserts. Oracle and DB2 support MERGE . MySQL has the sim- plified MERGE variants REPLACE INTO and INSERT ON DUPLICATE KEY UPDATE . ■ In Microsoft Access date liter- als, omit the DATE keyword 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 SET clause. To run Listing 10.13, split the UPDATE statement into two statements: one that SELECT s the pub_id for Abatis Publishers from publishers and one that uses this pub_id to change the pub_id of 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 statement. continues on next page 331 Inserting, Updating, and Deleting Rows Updating Rows with UPDATE In Microsoft SQL Server and DB2 date literals, omit the DATE keyword. 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 FROM clause 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). 332 Chapter 10 Updating Rows with UPDATE Deleting Rows with DELETE The DELETE statement removes rows from a table. You can use DELETE to 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 DELETE are: ◆ Unlike INSERT and UPDATE , DELETE takes no column names because it removes entire rows. ◆ DELETE removes 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. ◆ DELETE takes an optional WHERE clause that specifies which rows to delete. Without a WHERE clause, DELETE removes all the rows in the table. ◆ DELETE is dangerous because it’s easy to omit the WHERE clause mistakenly (and remove all rows) or misspecify the WHERE search condition (and remove the wrong rows). It’s wise to run a SELECT statement that uses the same WHERE clause before running the actual DELETE statement. 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 DELETE a 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. 333 Inserting, Updating, and Deleting Rows Deleting Rows with DELETE To 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 WHERE conditions (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 WHERE clause 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 WHERE clause tells the DBMS to delete all the rows. This state- ment deletes 13 rows; see Figure 10.11 for the result. The WHERE clause 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. 334 Chapter 10 Deleting Rows with DELETE 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 au_id au_fname au_lname phone address city state zip A01 Sarah Buchman 718-496-7223 75 West 205 St Bronx NY 10468 A02 Wendy Heydemark 303-986-7020 2922 Baseline Rd Boulder CO 80303 A05 Christian Kells 212-771-4680 114 Horatio St New York NY 10014 A06 Kellsey 650-836-7128 390 Serra Mall Palo Alto CA 94305 A07 Paddy O'Furniture 941-925-0752 1442 Main St Sarasota FL 34236 Figure 10.12 Result of Listing 10.15. You 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 from title_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 can DELETE rows through a view; see “Updating Data Through a View” in Chapter 13. ■ If you’re using transactions, you must use a COMMIT statement after your final DELETE statement to make the changes to the table permanent. For information about transactions, see Chapter 14. 335 Inserting, Updating, and Deleting Rows Deleting Rows with DELETE 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. ■ You can use a NOT EXISTS or NOT 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 titles for 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. 336 Chapter 10 Deleting Rows with DELETE Truncating Tables If you want to delete all the rows in a table, the TRUNCATE statement is faster than DELETE . TRUNCATE isn’t part of the SQL , standard, but Microsoft SQL Server, Oracle, MySQL, and PostgreSQL sup- port it. TRUNCATE works like a DELETE statement with no WHERE clause: Both remove all rows in a table. But TRUNCATE is faster and uses fewer system resources than DELETE because TRUNCATE doesn’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; table is the name of the table to be trun- cated. For information about TRUNCATE , search your DBMS documentation for truncate. To truncate a table in DB2, run LOAD with the REPLACE option, using a zero-byte file as input. Many 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: ◆ The CREATE TABLE statement creates a new table. ◆ The ALTER TABLE statement modifies the structure of an existing table. ◆ The DROP TABLE statement destroys a table and all its data. ◆ The CREATE TEMPORARY TABLE statement creates a table that the DBMS destroys automatically when it’s no longer in use. ◆ The CREATE TABLE AS statement 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. 337 Creating, Altering, and Dropping Tables 11 Creating, Altering, and Dropping Tables Creating 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 TABLE statement, 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. 338 Chapter 11 Creating Tables Understanding 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 constraint. 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 TABLE statement, for example. Constraint names are optional, but many SQL pro- grammers and database designers name all constraints. It’s not uncommon to leave a NOT NULL constraint unnamed, but you always should name other types of con- straints (even if I don’t do so in some of the examples). 339 Creating, Altering, and Dropping Tables Understanding Constraints Table 11.1 Constraints Constraint Description 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 . statement is faster than DELETE . TRUNCATE isn’t part of the SQL , standard, but Microsoft SQL Server, Oracle, MySQL, and PostgreSQL sup- port it. TRUNCATE works like a DELETE statement with. run Listing 10.11 because MySQL won’t let you use the same table ( titles , in this case) for both the sub- query’s FROM clause and the update target. Earlier MySQL versions don’t support subqueries. 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