Tải bản đầy đủ - 0 (trang)
2 Dropping, Adding, or Repositioning a Column

2 Dropping, Adding, or Repositioning a Column

Tải bản đầy đủ - 0trang

To remove a column from a table, use DROP followed by the column name. This statement

drops the i column, leaving only the c column in mytbl:



ALTER TABLE mytbl DROP i;



DROP will not work if the column is the only one left in the table. (To verify this, try to drop

the c column from mytbl after dropping the i column; an error will occur.)

To add a column, use ADD and specify the column definition. The following statement restores

the i column to mytbl:



ALTER TABLE mytbl ADD i INT;

After issuing this statement, mytbl will contain the same two columns that it had when you

first created the table, but will not have quite the same structure. That's because new columns

are added to the end of the table by default. So even though i originally was the first column

in mytbl, now it is the last one:



mysql> SHOW COLUMNS FROM mytbl;

+-------+---------+------+-----+---------+-------+

| Field | Type

| Null | Key | Default | Extra |

+-------+---------+------+-----+---------+-------+

| c

| char(1) | YES |

| NULL

|

|

| i

| int(11) | YES |

| NULL

|

|

+-------+---------+------+-----+---------+-------+

To indicate that you want a column at a specific position within the table, either use FIRST to

make it the first column, or AFTER col_name to indicate that the new column should be

placed after col_name. Try the following ALTER TABLE statements, using SHOW COLUMNS

after each one to see what effect each one has:



ALTER

ALTER

ALTER

ALTER



TABLE

TABLE

TABLE

TABLE



mytbl

mytbl

mytbl

mytbl



DROP i;

ADD i INT FIRST;

DROP i;

ADD i INT AFTER c;



The FIRST and AFTER specifiers work only with the ADD clause. This means that if you want

to reposition an existing column within a table, you first must DROP it and then ADD it at the

new position.



Column Repositioning and TIMESTAMP Columns

Be careful if you reposition columns in a table that contains more than one



TIMESTAMP column. The first TIMESTAMP column has special properties not shared

by the others. (See Recipe 5.32, which describes the differences.) If you change the

order of the TIMESTAMP columns, you'll change the way your table behaves.



8.3 Changing a Column Definition or Name

8.3.1 Problem

You want to change how a column is defined.



8.3.2 Solution

Use MODIFY or CHANGE. MODIFY is simpler, but cannot change the column name. CHANGE is

more confusing to use, but can change both the name and the definition.



8.3.3 Discussion

To change a column's definition, use MODIFY or CHANGE.



[1]



Of the two, MODIFY has the



simpler syntax: name the column, then specify its new definition. For example, to change

column c from CHAR(1) to CHAR(10), do this:

[1]



MODIFY requires MySQL 3.22.16 or later.



ALTER TABLE mytbl MODIFY c CHAR(10);

With CHANGE, the syntax is a bit different. After the CHANGE keyword, you name the column

you want to change, then specify the new definition, which includes the new name. The

second column name is required, because CHANGE also allows you to rename the column, not

just change its definition. For example, to change i from INT to BIGINT and rename it to j at

the same time, the statement looks like this:



ALTER TABLE mytbl CHANGE i j BIGINT;

If you now use CHANGE to convert j from BIGINT back to INT without changing the column

name, the statement may look a bit odd:



ALTER TABLE mytbl CHANGE j j INT;

At first glance, the statement seems incorrect—the column name appears to be given one too

many times. However, it's correct as written. The fact that the CHANGE syntax requires two

column names (even if they're both the same) is simply something you have to get used to.

This is especially important to remember if your version of MySQL is old enough that you can't

use MODIFY. Any ALTER TABLE statement that uses MODIFY col_name can be replaced by



one that uses CHANGE col_name col_name. That is, the following two statements are

equivalent:



ALTER TABLE tbl_name MODIFY col_name ... ;

ALTER TABLE tbl_name CHANGE col_name col_name ... ;

It would be nice to have a form of the ALTER TABLE statement that renamed a column

without the need to repeat the definition, especially for working with ENUM and SET columns

that have many member values. Unfortunately, there is no such statement, which makes

these column types somewhat difficult to work with when using ALTER TABLE. Suppose you

add to mytbl an ENUM column e that has several members:



ALTER TABLE mytbl ADD e

ENUM('hardware','software','books','office supplies',

'telecommunications','furniture','utilities',

'shipping','tax');

If you want to rename the column from e to e2, you use CHANGE to indicate the new name.

But you must also repeat the column definition as well:



ALTER TABLE mytbl CHANGE e e2

ENUM('hardware','software','books','office supplies',

'telecommunications','furniture','utilities',

'shipping','tax');

Ugh. That's too much typing. Manually entering the proper ALTER TABLE statement for this

kind of operation is quite a lot of work, not to mention error-prone. One way to avoid retyping

the definition is to capture the current definition in a file and edit the file to produce the proper



ALTER TABLE statement:





Run mysqldump to get the CREATE TABLE statement that contains the column

definition:



% mysqldump --no-data cookbook mytbl > test.txt

The resulting file, test.txt, should contain this statement:



CREATE TABLE mytbl (

c char(10) default NULL,

j bigint(20) NOT NULL default '100',

e enum('hardware','software','books','office

supplies','telecommunications',

'furniture','utilities','shipping','tax') default NULL

) TYPE=MyISAM;

The --no-data option tells mysqldump not to dump the data from the table; it's used

here because only the table creation statement is needed.







Edit the test.txt file to remove everything but the definition for the e column:







e enum('hardware','software','books','office

supplies','telecommunications',

'furniture','utilities','shipping','tax') default NULL







Modify the definition to produce an ALTER TABLE statement with a semicolon at the

end:









ALTER TABLE mytbl CHANGE e e2

enum('hardware','software','books','office

supplies','telecommunications',

'furniture','utilities','shipping','tax') default NULL;







Write test.txt back out to save it, then get out of the editor and feed test.txt as a

batch file to mysql:



% mysql cookbook < test.txt

For simple columns, this procedure is more work than just typing the ALTER TABLE statement

manually, of course. But for ENUM and SET columns with long and ungainly definitions, using

an editor to create a mysql batch file from mysqldump output makes a lot of sense. You can

also use this technique to make it easier to reorder the items in an ENUM or SET column, or to

add or delete members from the column definition. For another approach to column

manipulation, see Recipe 9.9, which develops a utility script that makes it trivial to add

member values. The script examines the table structure and uses that information to figure

out the proper ALTER TABLE statement for modifying an ENUM or SET column.



8.4 The Effect of ALTER TABLE on Null and Default Value Attributes

8.4.1 Problem

You changed a column definition, but MySQL modified the column's NULL value and default

value attributes when you didn't tell it to.



8.4.2 Solution

Those attributes are part of the column definition. If you don't specify them explicitly, MySQL

chooses their values for you. So just be more specific about how you want the column defined.



8.4.3 Discussion

When you MODIFY or CHANGE a column, you can also specify whether or not the column can

contain NULL values, and what its default value is. In fact, if you don't do this, MySQL

automatically assigns values for these attributes, with the result that the column may end up

defined not quite the way you intend. To see this, try the following sequence of commands.

First, modify j so that it cannot contain NULL values and to have a default value of 100, then

[2]



see what SHOW COLUMNS tells you:



[2]



The LIKE 'str' clause for SHOW COLUMNS causes the statement to

show information only for columns having names that match the string. The

string can contain SQL pattern characters if you want it to match several

column names. See Recipe 9.6.



mysql> ALTER TABLE mytbl MODIFY j INT NOT NULL DEFAULT 100;

mysql> SHOW COLUMNS FROM mytbl LIKE 'j';

+-------+---------+------+-----+---------+-------+

| Field | Type

| Null | Key | Default | Extra |

+-------+---------+------+-----+---------+-------+

| j

| int(11) |

|

| 100

|

|

+-------+---------+------+-----+---------+-------+

So far, so good. Now if you were to decide to change j from INT to BIGINT, you might try

the following statement:



mysql> ALTER TABLE mytbl MODIFY j BIGINT;

However, that also undoes the NULL and DEFAULT specifications of the previous ALTER



TABLE statement:

mysql> SHOW COLUMNS FROM mytbl LIKE 'j';

+-------+------------+------+-----+---------+-------+

| Field | Type

| Null | Key | Default | Extra |

+-------+------------+------+-----+---------+-------+

| j

| bigint(20) | YES |

| NULL

|

|

+-------+------------+------+-----+---------+-------+

To avoid this, the MODIFY statement should specify the null and default value attributes

explicitly:



mysql> ALTER TABLE mytbl MODIFY j BIGINT NOT NULL DEFAULT 100;

mysql> SHOW COLUMNS FROM mytbl LIKE 'j';

+-------+------------+------+-----+---------+-------+

| Field | Type

| Null | Key | Default | Extra |

+-------+------------+------+-----+---------+-------+

| j

| bigint(20) |

|

| 100

|

|

+-------+------------+------+-----+---------+-------+

The implication of this exercise is that if a column is defined such that its null and default

value attributes are not what MySQL would assign automatically, you must specify them

explicitly in your ALTER TABLE statement if you don't want them to change when you modify

some other aspect of the column definition.

This fact is important for some of the recipes shown in Chapter 9, such as one program that

converts a table to use VARCHAR rather than CHAR columns, and another that adds new

elements to ENUM or SET columns. In each case, the programs take care to avoid unintended

column changes by including NULL and DEFAULT specifiers in the ALTER TABLE statements

that they generate.



8.5 Changing a Column's Default Value

8.5.1 Problem

You want to leave a column definition alone except for the default value.



8.5.2 Solution

Use SET DEFAULT to specify the default value explicitly, or DROP DEFAULT to remove the

current default and allow MySQL to assign the "default default."



8.5.3 Discussion

A column's default value is part of its definition, but can be modified separately from other

aspects of the definition. To change a default value, use ALTER col_name SET DEFAULT:



ALTER TABLE mytbl ALTER j SET DEFAULT 1000;

Default values must be constants. For example, you cannot set the default for a date-valued

column to NOW( ), although that would be very useful.

To drop a default value, use ALTER col_name DROP DEFAULT:



ALTER TABLE mytbl ALTER j DROP DEFAULT;

In this case, the column's default value reverts to the standard default for the column type.

For columns that can contain NULL values, this will be NULL. Otherwise, the general defaults

are 0, the empty string, or the "zero" date or time for numeric, string, or date or time

columns, respectively. (The exceptions are for AUTO_INCREMENT, ENUM, and TIMESTAMP

columns, for which the defaults are the next sequence number, the first enumeration member,

and the current date and time.)



8.6 Changing a Table Type

8.6.1 Problem

A table has one type, and now you realize that another table type has properties that are

more desirable for the way you use the table.



8.6.2 Solution

Use ALTER TABLE to change its type with a TYPE clause.



8.6.3 Discussion



MySQL supports several tables types, each of which have differing characteristics. Sometimes

it's necessary or desirable to convert a table from one type to another. Some situations where

a change of table type can be useful are as follows:







Table conversions sometimes are done to gain access to features that are supported

by one table type but not another. For example, ISAM tables do not allow NULL values

in indexed columns. Also, AUTO_INCREMENT behavior in ISAM tables is such that

sequence values may be non-monotonic under certain conditions. (See Chapter 11, for

information about this.) You can convert an ISAM table to the MyISAM type, which

does not suffer from these problems. Or you might find that you need to perform

transactions on a table created using a type that doesn't provide transactional

capabilities. To handle this problem, you can alter the table to a type such as InnoDB

or BDB that does support transactions.







The oldest table type supported by MySQL is ISAM, but ISAM tables are deprecated

and at some point no longer will be supported. If you have ISAM tables, you should

convert them at some point to another table type. Otherwise, after ISAM support is

dropped, you'll be unable to upgrade to new releases of MySQL.



Changing a table type is easy; use ALTER TABLE with a TYPE specifier. For example, to

convert a table to the MyISAM type, use this statement:



ALTER TABLE tbl_name TYPE = MYISAM;

To find out the current type of a table, use the SHOW TABLE STATUS statement (introduced in

MySQL 3.23.0) or SHOW CREATE TABLE (introduced in MySQL 3.23.20):



mysql> SHOW TABLE STATUS LIKE 'mytbl'\G

*************************** 1. row ***************************

Name: mytbl

Type: MyISAM

Row_format: Fixed

Rows: 0

Avg_row_length: 0

Data_length: 0

Max_data_length: 85899345919

Index_length: 1024

Data_free: 0

Auto_increment: NULL

Create_time: 2002-07-15 21:28:34

Update_time: 2002-07-15 21:28:34

Check_time: NULL

Create_options:

Comment:

mysql> SHOW CREATE TABLE mytbl\G

*************************** 1. row ***************************

Table: mytbl

Create Table: CREATE TABLE `mytbl` (

`c` char(10) default NULL,

`j` bigint(20) default NULL,

`e2` enum('hardware','software','books','office supplies',

'telecommunications','furniture','utilities','shipping','tax') default NULL



) TYPE=MyISAM

Alternatively, use the mysqldump command-line utility:



% mysqldump --no-data cookbook mytbl

CREATE TABLE mytbl (

c char(10) default NULL,

j bigint(20) default NULL,

e2 enum('hardware','software','books','office supplies',

'telecommunications','furniture','utilities','shipping','tax') default NULL

) TYPE=MyISAM;



8.7 Renaming a Table

8.7.1 Problem

A table needs to be renamed.



8.7.2 Solution

You can use ALTER TABLE or RENAME TABLE for this.



8.7.3 Discussion

To rename a table, use the RENAME option of the ALTER TABLE statement:



ALTER TABLE old_name RENAME TO new_name;

As of Version 3.23.23, MySQL includes an explicit RENAME TABLE statement:



RENAME TABLE old_name TO new_name;



RENAME TABLE allows you to rename multiple tables, which allows you to do things such as

swap the names of two tables in a single statement:



RENAME TABLE name1 TO temp_name, name2 TO name1, tmp_name to name2;

You can achieve the same result with ALTER TABLE, except that you need three separate

statements. Because of that, the tables become available to other clients in the brief intervals

between statements, which may be undesirable. Using a single RENAME TABLE statement

avoids this problem.



RENAME TABLE is also useful for rotating tables. To do this without having an interval in which

the log table is unavailable to clients, create an empty version under a temporary name, then

rotate the files using a single RENAME TABLE statement. For example, if you want to keep

monthly log tables, named using the year and month, you might do something like this:



CREATE TABLE log_temp (...);



RENAME TABLE log TO log_2001_05, log_temp TO log;

To rotate log tables to keep a set of daily tables covering the last week, you could run the

following statements daily:



CREATE TABLE log_temp (...);

DROP TABLE IF exists log_7;

RENAME TABLE log_6 TO log_7,

log_5 TO log_6,

log_4 TO log_5,

log_3 TO log_4,

log_2 TO log_3,

log_1 TO log_2,

log TO log_1,

log_tmp TO log;



8.8 Adding or Dropping Indexes

8.8.1 Problem

Table lookups are slow. Or INSERTS and UPDATES are slow.



8.8.2 Solution



ALTER TABLE can not only drop or add columns, it can drop or add indexes on those columns.

These operations often are useful for improving the performance of a database. Typically,

indexing a column that you query frequently helps SELECT statements run faster because the

index allows MySQL to avoid full table scans. Dropping indexes can sometimes be useful as

well. Whenever a row is modified, MySQL must update any indexes that include the modified

columns. If you don't actually use a particular index very much, it's possible that your table is

overindexed and that dropping the index will speed up performance of table updates.



8.8.3 Discussion

For the discussion in this section, it's useful to begin again with a new copy of the mytbl

example table. Use DROP TABLE and CREATE TABLE to remove the existing version and

recreate it in its original form:



DROP TABLE mytbl;

CREATE TABLE mytbl

(

i

INT,

c

CHAR(1)

);

In earlier sections of this chapter, SHOW COLUMNS was used to see the effect of table

modifications. For index-changing operations, use SHOW INDEX rather than SHOW COLUMNS.

Currently, the table has no indexes, because none were specified in the CREATE TABLE

statement:



mysql> SHOW INDEX FROM mytbl;

Empty set (0.00 sec)

8.8.4 Adding Indexes

There are four types of statements for adding indexes to a table:



ALTER

ALTER

ALTER

ALTER



TABLE

TABLE

TABLE

TABLE



tbl_name

tbl_name

tbl_name

tbl_name



ADD

ADD

ADD

ADD



PRIMARY KEY (column_list);

UNIQUE index_name (column_list);

INDEX index_name (column_list);

FULLTEXT index_name (column_list);



The first statement adds a PRIMARY KEY, which means that indexed values must be unique

and cannot be NULL. The second creates an index for which values must be unique (with the

exception of NULL values, which may appear multiple times). The third adds an ordinary index

in which any value may appear more than once. The fourth creates a special FULLTEXT index

that is used for text-searching purposes. FULLTEXT searches are discussed in more detail in

Recipe 4.12.

For those statements that include index_name in the syntax, the index name is optional. If

you don't specify a name, MySQL assigns one automatically. column_list indicates which

columns to index; it should be a list of one or more column names separated by commas. As

simple examples, the first of the following statements creates a single-column index on c, and

the second creates a multiple-column index that includes both c and i:



ALTER TABLE mytbl ADD INDEX (c);

ALTER TABLE mytbl ADD INDEX (c,i);

In many cases, indexed columns must be declared NOT NULL. For example, if you create



mytbl as an ISAM table type, the preceding ADD INDEX statements will fail because ISAM

tables do not allow NULL in any kind of index. And no matter what the table type, columns in

a PRIMARY KEY cannot contain NULL values. If you try to add an index and MySQL issues a



NULL-related complaint, use ALTER TABLE to change the relevant column or columns to NOT

NULL and then try adding the index again. For example, if you try to make column i a

PRIMARY KEY as follows, an error results:

mysql> ALTER TABLE mytbl ADD PRIMARY KEY (i);

ERROR 1171 at line 5: All parts of a PRIMARY KEY must be NOT NULL;

If you need NULL in a key, use UNIQUE instead

To deal with this, redefine i to be NOT NULL, then try again:



mysql> ALTER TABLE mytbl MODIFY i INT NOT NULL;

mysql> ALTER TABLE mytbl ADD PRIMARY KEY (i);

Alternatively, as the error message indicates, you can create a UNIQUE index rather than a



PRIMARY KEY should you wish to allow NULL values in the index.



8.8.5 Dropping Indexes

To drop an index, use one of the following statements:



ALTER TABLE tbl_name DROP PRIMARY KEY;

ALTER TABLE tbl_name DROP INDEX index_name;

Dropping a PRIMARY KEY is easiest, because you need not know the index name:



ALTER TABLE mytbl DROP PRIMARY KEY;

To drop an index that is not a PRIMARY KEY, you must specify the index name. If you don't

know the name, use SHOW INDEX. Vertical-format output (specified by \G) often is useful with

this statement, to avoid long line wraparound:



mysql> SHOW INDEX FROM mytbl\G

*************************** 1. row ***************************

Table: mytbl

Non_unique: 1

Key_name: c

Seq_in_index: 1

Column_name: c

Collation: A

Cardinality: NULL

Sub_part: NULL

Packed: NULL

Comment:

*************************** 2. row ***************************

Table: mytbl

Non_unique: 1

Key_name: c_2

Seq_in_index: 1

Column_name: c

Collation: A

Cardinality: NULL

Sub_part: NULL

Packed: NULL

Comment:

*************************** 3. row ***************************

Table: mytbl

Non_unique: 1

Key_name: c_2

Seq_in_index: 2

Column_name: i

Collation: A

Cardinality: NULL

Sub_part: NULL

Packed: NULL

Comment:

The Key_name and Seq_in_index values show the index names and the positions of

columns within an index. Those values indicate in the preceding output that mytbl has a

single-column index named c and a multiple-column index named c_2. (These are the names



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

2 Dropping, Adding, or Repositioning a Column

Tải bản đầy đủ ngay(0 tr)

×