You can run an existing SQL file, such as one loaded from the CD-ROM, through MySQL by typing > mysql -h host -u bookorama books -p < bookorama.sql Using file redirection is pretty handy for this because it means that you can edit your SQL in the text editor of your choice before executing it. LISTING 8.1 bookorama.sql—SQL to Create the Tables for Book-O-Rama create table customers ( customerid int unsigned not null auto_increment primary key, name char(30) not null, address char(40) not null, city char(20) not null ); create table orders ( orderid int unsigned not null auto_increment primary key, customerid int unsigned not null, amount float(6,2), date date not null ); create table books ( isbn char(13) not null primary key, author char(30), title char(60), price float(4,2) ); create table order_items ( orderid int unsigned not null, isbn char(13) not null, quantity tinyint unsigned, primary key (orderid, isbn) ); create table book_reviews ( isbn char(13) not null primary key, review text ); Creating Your Web Database C HAPTER 8 8 CREATING YOUR WEB DATABASE 195 11 7842 CH08 3/6/01 3:38 PM Page 195 Each of the tables is created by a separate CREATE TABLE statement. You see that we’ve created each of the tables in the schema with the columns that we designed in the last chapter. You’ll see that each of the columns has a data type listed after its name. Some of the columns have other specifiers, too. What the Other Keywords Mean NOT NULL means that all the rows in the table must have a value in this attribute. If it isn’t specified, the field can be blank (NULL). AUTO_INCREMENT is a special MySQL feature you can use on integer columns. It means if we leave that field blank when inserting rows into the table, MySQL will automatically generate a unique identifier value. The value will be one greater than the maximum value in the column already. You can only have one of these in each table. Columns that specify AUTO_INCREMENT must be indexed. PRIMARY KEY after a column name specifies that this column is the primary key for the table. Entries in this column have to be unique. MySQL will automatically index this column. Notice that where we’ve used it above with customerid in the customers table we’ve used it with AUTO_INCREMENT. The automatic index on the primary key takes care of the index required by AUTO_INCREMENT. Specifying PRIMARY KEY after a column name can only be used for single column primary keys. The PRIMARY KEY clause at the end of the order_items statement is an alternative form. We have used it here because the primary key for this table consists of the two columns together. UNSIGNED after an integer type means that it can only have a zero or positive value. Understanding the Column Types Let’s take the first table as an example: create table customers ( customerid int unsigned not null auto_increment primary key, name char(30) not null, address char(40) not null, city char(20) not null ); When creating any table, you need to make decisions about column types. With the customers table, we have four columns as specified in our schema. The first one, customerid, is the primary key, which we’ve specified directly. We’ve decided this will be an integer (data type int) and that these IDs should be unsigned. We’ve also taken advantage of Using MySQL P ART II 196 11 7842 CH08 3/6/01 3:38 PM Page 196 the auto_increment facility so that MySQL can manage these for us—it’s one less thing to worry about. The other columns are all going to hold string type data. We’ve chosen the char type for these. This specifies fixed width fields. The width is specified in the brackets, so, for example, name can have up to 30 characters. This data type will always allocate 30 characters of storage for the name, even if they’re not all used. MySQL will pad the data with spaces to make it the right size. The alternative is varchar, which uses only the amount of storage required (plus one byte). It’s a small trade off—varchars will use less space but chars are faster. For real customers with real names and real addresses, these column widths will be far too narrow. Note that we’ve declared all the columns as NOT NULL. This is a minor optimization you can make wherever possible that also will make things run a bit faster. We’ll talk more about optimization in Chapter 11. Some of the other CREATE statements have variations in syntax. Let’s look at the orders table: create table orders ( orderid int unsigned not null auto_increment primary key, customerid int unsigned not null, amount float(6,2), date date not null ); The amount column is specified as a floating point number of type float. With most floating point data types, you can specify the display width and the number of decimal places. In this case, the order amount is going to be in dollars, so we’ve allowed a reasonably large order total (width 6) and two decimal places for the cents. The date column has the data type date. In this particular table, we’ve specified that all columns bar the amount as NOT NULL. Why? When an order is entered into the database, we’ll need to create it in orders, add the items to order_items, and then work out the amount. We might not know the amount when the order is created, so we’ve allowed for it to be NULL. The books table has some similar characteristics: create table books ( isbn char(13) not null primary key, author char(30), title char(60), price float(4,2) ); Creating Your Web Database C HAPTER 8 8 CREATING YOUR WEB DATABASE 197 11 7842 CH08 3/6/01 3:38 PM Page 197 In this case, we don’t need to generate the primary key because ISBNs are generated elsewhere. We’ve left the other fields NULL because a bookstore might know the ISBN of a book before they know the title, author, or price. The order_items table demonstrates how to create multicolumn primary keys: create table order_items ( orderid int unsigned not null, isbn char(13) not null, quantity tinyint unsigned, primary key (orderid, isbn) ); We’ve specified the quantity of a particular book as a TINYINT UNSIGNED, which holds an inte- ger between 0 and 255. As we mentioned before, multicolumn primary keys need to be specified with a special pri- mary key clause. This is used here. Lastly, if you consider the book_reviews table: create table book_reviews ( isbn char(13) not null primary key, review text ); This uses a new data type, text, which we have not yet discussed. It is used for longer text, such as an article. There are a few variants on this, which we’ll discuss later in this chapter. To understand creating tables in more detail, let’s discuss column names and identifiers in gen- eral, and then the data types we can choose for columns. First though, let’s look at the database we’ve created. Looking at the Database with SHOW and DESCRIBE Log in to the MySQL monitor and use the books database. You can view the tables in the data- base by typing mysql> show tables; MySQL will display a list of all the tables in the database: + + | Tables in books | + + | book_reviews | | books | Using MySQL P ART II 198 11 7842 CH08 3/6/01 3:38 PM Page 198 | customers | | order_items | | orders | + + 5 rows in set (0.06 sec) You can also use show to see a list of databases by typing mysql> show databases; You can see more information about a particular table, for example, books, using DESCRIBE: mysql> describe books; MySQL will display the information you supplied when creating the database: + + + + + + + | Field | Type | Null | Key | Default | Extra | + + + + + + + | isbn | char(13) | | PRI | | | | author | char(30) | YES | | NULL | | | title | char(60) | YES | | NULL | | | price | float(4,2) | YES | | NULL | | + + + + + + + 4 rows in set (0.05 sec) These commands are useful to remind yourself of a column type, or to navigate a database that you didn’t create. MySQL Identifiers There are four kinds of identifiers in MySQL—databases, tables, and columns, which we’re familiar with, and aliases, which we’ll cover in the next chapter. Databases in MySQL map to directories in the underlying file structure, and tables map to files. This has a direct effect on the names you can give them. It also affects the case sensitivity of these names—if directory and filenames are case sensitive in your operating system, data- base and table names will be case sensitive (for example, in UNIX), otherwise they won’t (for example, under Windows). Column names and alias names are not case sensitive, but you can’t use versions of different cases in the same SQL statement. As a side note, the location of the directory and files containing the data will be wherever it was set in configuration. You can check the location on your system by using the mysqladmin facility as follows: mysqladmin variables Creating Your Web Database C HAPTER 8 8 CREATING YOUR WEB DATABASE 199 11 7842 CH08 3/6/01 3:38 PM Page 199 A summary of possible identifiers is shown in Table 8.4. The only additional exception is that you cannot use ASCII(0) or ASCII(255) in identifiers (and to be honest, I’m not sure why you’d want to). TABLE 8.4 MySQL Identifiers Max Case Characters Type Length Sensitive? Allowed Database 64 same as O/S Anything allowed in a directory name in your O/S except the / character Table 64 same as O/S Anything allowed in a filename in your O/S except the / and . characters Column 64 no Anything Alias 255 no Anything These rules are extremely open. As of MySQL 3.23.6, you can even have reserved words and special characters of all kinds in identifiers, the only limitation being that if you use anything weird like this, you have to put it in back quotes (located under the tilde key on the top left of most keyboards). For example create database `create database`; The rules in versions of MySQL (prior to 3.23.6) are more restrictive, and don’t allow you to do this. Of course, you should apply common sense to all this freedom. Just because you can call a database `create database`, it doesn’t that mean that you should. The same principle applies as in any other kind of programming—use meaningful identifiers. Column Data Types The three basic column types in MySQL are: numeric, date and time, and string. Within each of these categories are a large number of types. We’ll summarize them here, and go into more detail about the strengths and weaknesses of each in Chapter 11. Each of the three types comes in various storage sizes. When choosing a column type, the prin- ciple is generally to choose the smallest type that your data will fit into. For many data types, when you are creating a column of that type, you can specify the maxi- mum display length. This is shown in the following tables of data types as M. If it’s optional for that type, it is shown in square brackets. The maximum value you can specify for M is 255. Optional values throughout these descriptions are shown in square brackets. Using MySQL P ART II 200 11 7842 CH08 3/6/01 3:38 PM Page 200 Numeric Types The numeric types are either integers or floating point numbers. For the floating point num- bers, you can specify the number of digits after the decimal place. This is shown in this book as D. The maximum value you can specify for D is 30 or M-2 (that is, the maximum display length minus two—one character for a decimal point and one for the integral part of the num- ber), whichever is lower. For integer types you can also specify if you want them to be UNSIGNED, as shown in Listing 8.1. For all numeric types, you can also specify the ZEROFILL attribute. When values from a ZERO- FILL column are displayed, they will be padded with leading zeroes. The integral types are shown in Table 8.5. Note that the ranges shown in this table show the signed range on one line and the unsigned range on the next. TABLE 8.5 Integral Data Types Storage Type Range (Bytes) Description TINYINT[(M)] -127 128 1 Very small integers or 0 255 SMALLINT[(M)] -32768 32767 2 Small integers or 0 65535 MEDIUMINT[(M)] -8388608 3 Medium-sized integers 8388607 or 0 16777215 INT[(M)] -2 31 2 31 -1 4 Regular integers or 0 2 32 -1 INTEGER[(M)] Synonym for INT BIGINT[(M)] -2 63 2 63 -1 8 Big integers or 0 2 64 -1 The floating point types are shown in Table 8.6. Creating Your Web Database C HAPTER 8 8 CREATING YOUR WEB DATABASE 201 11 7842 CH08 3/6/01 3:38 PM Page 201 TABLE 8.6 Floating Point Data Types Storage Type Range (Bytes) Description FLOAT(precision) depends on varies Can be used to specify precision single or double precision floating point numbers. FLOAT[(M,D)] ±1.175494351E-38 4 Single precision ±3.402823466E+38 floating point number. These are equivalent to FLOAT(4), but with a specified display width and number of decimal places. DOUBLE[(M,D)] ±1.7976931348623157E 8 Doubleprecision +308 floating point number. ±2.2250738585072014E These are equivalent -308 to FLOAT(8)but with a specified display width and number of decimal places. DOUBLE Synonym for PRECISION[(M,D)] as above DOUBLE[(M, D)]. REAL[(M,D)] as above Synonym for DOUBLE[(M, D)]. DECIMAL[(M[,D])] varies M+2 Floating point number stored as char. The range depends on M,the display width. NUMERIC[(M,D)] as above Synonym for DECIMAL. Using MySQL P ART II 202 11 7842 CH08 3/6/01 3:38 PM Page 202 Date and Time Types MySQL supports a number of date and time types. These are shown in Table 8.7. With all these types, you can input data in either a string or numerical format. It is worth noting that a TIMESTAMP column in a particular row will be set to the date and time of the most recent opera- tion on that row if you don’t set it manually. This is useful for transaction recording. TABLE 8.7 Date and Time Data Types Type Range Description DATE 1000-01-01 A date. Will be displayed as YYYY-MM-DD. 9999-12-31 TIME -838:59:59 A time. Will be displayed as HH:MM:SS. 838:59:59 Note that the range is much wider than you will probably ever want to use. DATETIME 1000-01-01 A date and time. Will be displayed as 00:00:00 YYYY-MM-DDHH:MM:SS. 9999-12-31 23:59:59 TIMESTAMP[(M)] 1970-01-01 A timestamp, useful for transaction 00:00:00 reporting. The display format depends on the value of M (see Table 8.8, which follows). Sometime The top of the range depends on the limit in 2037 on UNIX. timestamps. YEAR[(2|4)] 70–69 A year. You can specify 2 or 4 digit format. (1970–2069) Each of these has a different range, as 1901–2155 shown. Table 8.8 shows the possible different display types for TIMESTAMP. T ABLE 8.8 TIMESTAMP Display Types Type Specified Display TIMESTAMP YYYYMMDDHHMMSS TIMESTAMP(14) YYYYMMDDHHMMSS TIMESTAMP(12) YYMMDDHHMMSS TIMESTAMP(10) YYMMDDHHMM TIMESTAMP(8) YYYYMMDD TIMESTAMP(6) YYMMDD TIMESTAMP(4) YYMM TIMESTAMP(2) YY Creating Your Web Database C HAPTER 8 8 CREATING YOUR WEB DATABASE 203 11 7842 CH08 3/6/01 3:38 PM Page 203 String Types String types fall into three groups. First, there are plain old strings, that is, short pieces of text. These are the CHAR (fixed length character) and VARCHAR (variable length character) types. You can specify the width of each. Columns of type CHAR will be padded with spaces to the maxi- mum width regardless of the size of the data, whereas VARCHAR columns vary in width with the data. (Note that MySQL will strip the trailing spaces from CHARs when they are retrieved, and from VARCHARs when they are stored.) There is a space versus speed trade off with these two types, which we will discuss in more detail in Chapter 11. Second, there are TEXT and BLOB types. These come in various sizes. These are for longer text or binary data, respectively. BLOBs are binary large objects. These can hold anything you like, for example, image or sound data. In practice, BLOB and TEXT columns are the same except that TEXT is case sensitive and BLOB is not. Because these column types can hold large amounts of data, they require some special considerations. We will discuss this in Chapter 11. The third group has two special types, SET and ENUM. The SET type is used to specify that val- ues in this column must come from a particular set of specified values. Column values can contain more than one value from the set. You can have a maximum of 64 things in the speci- fied set. ENUM is an enumeration. It is very similar to SET, except that columns of this type can have only one of the specified values or NULL, and that you can have a maximum of 65535 things in the enumeration. We’ve summarized the string data types in Tables 8.9, 8.10, and 8.11. Table 8.9 shows the plain string types. TABLE 8.9 Regular String Types Type Range Description [NATIONAL] 1 to 255 Fixed length string of length M, where M CHAR(M) [BINARY] characters is between 1 and 255. The NATIONAL key- word specifies that the default character set should be used. This is the default in MySQL anyway, but is included as it is part of the ANSI SQL standard. The BINARY key- word specifies that the data should be treated as not case insensitive. (The default is case sensitive.) [NATIONAL] 1 to 255 Same as above, except they are VARCHAR(M) characters variable length. [BINARY] Using MySQL P ART II 204 11 7842 CH08 3/6/01 3:38 PM Page 204 . than you will probably ever want to use. DATETIME 100 0-0 1-0 1 A date and time. Will be displayed as 00:00:00 YYYY-MM-DDHH:MM:SS. 999 9-1 2-3 1 23: 59:59 TIMESTAMP[(M)] 197 0-0 1-0 1 A timestamp, useful for. recording. TABLE 8.7 Date and Time Data Types Type Range Description DATE 100 0-0 1-0 1 A date. Will be displayed as YYYY-MM-DD. 999 9-1 2-3 1 TIME -8 38:59:59 A time. Will be displayed as HH:MM:SS. 838:59:59 Note. Your Web Database C HAPTER 8 8 CREATING YOUR WEB DATABASE 201 11 7842 CH08 3/6/01 3:38 PM Page 201 TABLE 8.6 Floating Point Data Types Storage Type Range (Bytes) Description FLOAT(precision) depends